Comando Grep para buscar archivos que contengan cadenas de texto y moverlos

15

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?

Spartanblogger
fuente
Aquí está. grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name
Alan Dong

Respuestas:

10

Como siempre, ten cuidado grep -r. -rno 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.

Stéphane Chazelas
fuente
esto me da error find: 'grep' terminado por la señal 13. ¿alguna idea de qué va mal?
Reena Parekh
@ReenaParekh, eso sería un SIGPIPE. Eso solo sucedería si xargssale 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.
Stéphane Chazelas
15

Usar xargsen concierto con mvla 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 greptiene la opción -Z/ --nullpara terminar nombres de archivo NUL.

Una alternativa a la tercera sintaxis mves usar xargscon 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.

Peterph
fuente
3
gnu grep admite una bandera -Z para separar los nombres de archivo por el carácter de cero bytes, que cuando se usa junto con la bandera -0 para xargs, puede evitar el problema de caracteres especiales que mencionas
iruvar el
@ChandraRavoori gracias, he actualizado la respuesta.
Peter
7

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/
ire_and_curses
fuente
Los backticks están en desuso; use el $ (...) más portátil, legible y apilable en su lugar.
usuario desconocido
2

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 -Fopción (búsqueda de cadena fija) grepparece 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.

Especificaciones POSIX para grep

Especificaciones POSIX para find

Comodín
fuente
Esta podría ser la mejor solución en Macos / BSD
Ali
0

Usando GNU paralelo :

grep -i -Z -r -l 'string' . | parallel 'mv {} destination/{}'

ht / @ lin-dong por su respuesta original con xargs.

zach
fuente
Hubiera sido agradable si hubieras acreditado la respuesta de @ lindong en los comentarios de hace más de un año.
roaima el
0

-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 /

SURESH BABU
fuente