Estoy tratando de ejecutar grep contra una lista de unos cientos de archivos:
$ head -n 3 <(cat files.txt)
admin.php
ajax/accept.php
ajax/add_note.php
Sin embargo, aunque estoy buscando una cadena que sé que se encuentra en los archivos, lo siguiente no busca los archivos:
$ grep -i 'foo' <(cat files.txt)
$ grep -i 'foo' admin.php
The foo was found
Estoy familiarizado con la -f
bandera que leerá los patrones de un archivo. Pero, ¿cómo leer los archivos de entrada ?
Había considerado la horrible solución de copiar los archivos a un directorio temporal, ya que cp
parece admitir el <(cat files.txt)
formato, y a partir de ahí agrupar los archivos. Shirley hay una mejor manera.
fuente
while
podría recibir las líneas de file.txt como tal.while
no está recibiendo exactamente las líneas del archivo,read
está haciendo eso;while
solo nos deja hacer eso en un bucle. El ciclo finaliza cuandoread
falla (es decir, devuelve un código de retorno distinto de cero), normalmente debido a que se alcanza el Fin del archivo.IFS= read -r filename
,read filename
es otra cosa.-H
es una extensión GNU. Te estás perdiendo un poco--
.suponiendo que los archivos estén en blanco o delimitados por nueva línea (donde las comillas o barras invertidas pueden usarse para escapar de esos separadores). Con GNU
xargs
puede especificar el delimitador con-d
(que luego deshabilita el manejo de las comillas).suponiendo que los archivos estén separados por espacio, tabulación o nueva línea (no hay forma de escapar de ellos, aunque puede elegir un separador diferente asignándolo a
IFS
). Ese fallará si la lista de archivos es demasiado grande en la mayoría de los sistemas.También se supone que ninguno de los archivos se llama
-
.fuente
$(< file)
lugar de$(cat file)
, al menos enbash
yzsh
.Para leer una lista de nombres de archivo de stdin puede usar
xargs
. P.ej,Por defecto,
xargs
lee elementos de la entrada estándar, delimitados por espacios en blanco. El-d'\n'
le dice que use nueva línea como delimitador de argumento, para que pueda manejar nombres de archivos que contienen espacios en blanco. (Como señala Stéphane Chazelas, esa es una extensión de GNU). Sin embargo, no hará frente a los nombres de archivo que contienen nuevas líneas; necesitaríamos un enfoque un poco más complicado para manejarlos.FWIW, este enfoque es algo más rápido que un
while read
bucle, ya que elread
comando de bash es muy lento: lee sus datos carácter por carácter, mientras quexargs
lee su entrada de manera más eficiente. Además,xargs
solo invoca elgrep
comando tantas veces como sea necesario, con cada invocación recibiendo múltiples nombres de archivo, y eso es más eficiente que invocargrep
individualmente para cada nombre de archivo.Consulte la página de manual de xargs y la página de información de xargs para obtener más detalles.
fuente
xargs
puede leer elementos de un archivo (como sufiles.txt
lista) con su opción:Entonces esto también debería funcionar:
o para espacios en nombres de archivo
fuente
También puedes hacer un for pero el ejemplo de Orion es el más simple:
(Para cada archivo listado en files.txt, ejecute el comando grep en él).
fuente