Puedo ubicar archivos en una carpeta que contiene una cadena de texto específica usando este comando:
grep -lir 'string' ~/directory/*
¿Cómo muevo los archivos que aparecen en el resultado anterior a otra ubicación?
Puedo ubicar archivos en una carpeta que contiene una cadena de texto específica usando este comando:
grep -lir 'string' ~/directory/*
¿Cómo muevo los archivos que aparecen en el resultado anterior a otra ubicación?
Respuestas:
Como siempre, ten cuidado grep -r
. -r
no es una opción estándar, y en algunas implementaciones como todas las versiones de GNU grep
, excepto las muy recientes , sigue enlaces simbólicos al descender el árbol de directorios, que generalmente no es lo que desea y puede tener graves consecuencias si, por ejemplo, hay un enlace simbólico a "/ "en algún lugar del árbol de directorios.
En la filosofía de Unix, utiliza un comando para buscar directorios en los archivos y otro para ver su contenido.
Usando herramientas GNU, haría:
xargs -r0 --arg-file <(find . -type f -exec grep -lZi string {} +
) mv -i --target-directory /dest/dir
Pero incluso entonces, tenga cuidado con las condiciones de carrera y los posibles problemas de seguridad si lo ejecuta como un usuario en un directorio que otro usuario puede escribir.
xargs
sale antes de leer hasta el final de su archivo arg, lo que no debería suceder a menos que xargs se mate o falle por algún motivo, en cuyo caso esperaría que también vea un error al respecto.
Usar xargs
en concierto con mv
la tercera sintaxis de:mv [OPTION]... -t DIRECTORY SOURCE...
grep -lir 'string' ~/directory/* | xargs mv -t DEST
Tenga cuidado con los archivos que contienen caracteres especiales (espacios, comillas). Si este es su caso, puede ser útil filtrar la lista con sed
(agregando comillas alrededor de los nombres de archivo con s/^/'/;s/$/'/
), pero debe asegurarse, estas comillas no aparecerán en los nombres de archivo. GNU grep
tiene la opción -Z
/ --null
para terminar nombres de archivo NUL.
Una alternativa a la tercera sintaxis mv
es usar xargs
con la cadena de marcador de posición ( -I
).
Otra opción es la sustitución de comandos $( )
o backticks ``
(en bash) como se menciona en la respuesta de ire_and_curses.
Si los nombres de sus archivos no contienen caracteres especiales (espacios en blanco o \[*?
), use la sustitución de comandos :
mv `grep -lir 'string' ~/directory/*` destination/
Usando solo las características especificadas de POSIX y sin hacer suposiciones sobre los nombres de archivo:
find ~/directory -type f -exec grep -qiF 'string' {} \; -exec mv {} /path/to/dest \;
Notas:
Dijiste "cadena", no "patrón", por lo que la -F
opción (búsqueda de cadena fija) grep
parece apropiada.
Si su directorio de destino está en algún lugar dentro de su directorio de búsqueda, puede tener algunas condiciones de carrera desagradables.
Usando GNU paralelo :
grep -i -Z -r -l 'string' . | parallel 'mv {} destination/{}'
ht / @ lin-dong por su respuesta original con xargs.
-Suponga que tiene el directorio de destino como 'externo' y necesita mover todos los archivos XLS, puede probar el siguiente comando
sudo mv find /var/log/ -type f -name "*.xls"
/ externo /
grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name