Estoy haciendo una find
y luego obtengo una lista de archivos. ¿Cómo lo canalizo a otra utilidad como cat
(para que cat muestre el contenido de todos esos archivos) y básicamente necesito grep
algo de estos archivos?
Estoy haciendo una find
y luego obtengo una lista de archivos. ¿Cómo lo canalizo a otra utilidad como cat
(para que cat muestre el contenido de todos esos archivos) y básicamente necesito grep
algo de estos archivos?
Respuestas:
Tubería a otro proceso (aunque esto NO logrará lo que dijo que está tratando de hacer):
command1 | command2
Esto enviará la salida del comando1 como la entrada del comando2
-exec
en un find
(esto hará lo que desea hacer, pero es específico para find
)
find . -name '*.foo' -exec cat {} \;
(Todo entre find
y -exec
son los predicados de búsqueda que ya estaba usando. {}
Sustituirá el archivo particular que encontró en el comando ( cat {}
en este caso); \;
es para finalizar el -exec
comando).
enviar la salida de un proceso como argumentos de línea de comando a otro proceso
command2 `command1`
por ejemplo:
cat `find . -name '*.foo' -print`
(Tenga en cuenta que estos no son VOLVER comillas citas regulares (bajo la tilde ~ en mi teclado).) Esto enviará la salida command1
en command2
como argumentos de línea de comandos. Sin embargo, tenga en cuenta que los nombres de archivo que contienen espacios (líneas nuevas, etc.) se dividirán en argumentos separados.
find
permiten escribir:, find . -name '*.foo' -exec cat {} +
donde +
indica que find
debe agrupar tantos nombres de archivos como sea conveniente en una sola invocación de comando. Esto es bastante útil (se trata de espacios, etc. en los nombres de archivo sin recurrir a -print0
y xargs -0
).
find . -name '*.foo' | xargs cat
find . -name '*.foo' | xargs cat | grep string
POSIX 2008 agregó el +
marcador, lo find
que significa que ahora agrupa automáticamente tantos archivos como sea razonable en una sola ejecución de comando, de manera muy similar xargs
, pero con una serie de ventajas:
El problema del nombre del archivo es un problema xargs
sin la -0
opción, y el problema de 'ejecutar incluso con cero nombres de archivo' es un problema con o sin la -0
opción, pero GNU xargs
tiene la opción -r
o --no-run-if-empty
para evitar que eso suceda. Además, esta notación reduce el número de procesos, no es probable que mida la diferencia en el rendimiento. Por lo tanto, podrías escribir sensatamente:
find . -exec grep something {} +
find . -print | xargs grep something
Si estás en Linux o tienes GNU find
y xargs
comandos, use -print0
con find
y -0
con xargs
para manejar nombres de archivos que contienen espacios y otros caracteres extraños.
find . -print0 | xargs -0 grep something
grep
Si no desea los nombres de archivo (solo el texto), agregue una opción adecuada grep
(generalmente -h
para suprimir 'encabezados'). Para garantizar absolutamente que se imprima el nombre del archivo grep
(incluso si solo se encuentra un archivo, o la última invocación de grep
solo se le da 1 nombre de archivo), luego agregue/dev/null
a la xargs
línea de comando, para que siempre haya al menos dos nombres de archivo.
xargs grep something
.
find
se canaliza a la entrada estándar de xargs
. El xargs
programa lee su entrada estándar, divide la entrada en el espacio en blanco (espacios en blanco, líneas nuevas, pestañas, etc.) y agrega varias palabras al comando grep something
y ejecuta la línea de comando. xargs
luego continúa leyendo la entrada y ejecutando comandos hasta que se agota la entrada. xargs
ejecuta el grep
comando con la frecuencia necesaria para la entrada que se le da ( find
en este ejemplo).
/dev/null
perder los mensajes de error.
Hay algunas maneras de pasar la lista de archivos devueltos por el find
comando al cat
comando, aunque técnicamente no todos usan tuberías, y ninguna de ellas se canaliza directamente cat
.
Lo más simple es usar backticks ( `
):
cat `find [whatever]`
Esto toma el resultado find
y lo coloca efectivamente en la línea de comando de cat
. Esto no funciona bien si find
tiene demasiada salida (más de la que cabe en una línea de comandos) o si la salida tiene caracteres especiales (como espacios).
En algunos shells, incluidos bash
, uno puede usar en $()
lugar de backticks:
cat $(find [whatever])
Esto es menos portátil, pero es anidable. Aparte de eso, tiene casi las mismas advertencias que los backticks.
Debido a que ejecutar otros comandos en lo que se encontró es un uso común find
, find tiene una -exec
acción que ejecuta un comando para cada archivo que encuentra:
find [whatever] -exec cat {} \;
El {}
es un marcador de posición para el nombre de archivo y \;
marca el final del comando (es posible tener otras acciones después -exec
).
Esto se ejecutará cat
una vez para cada archivo en lugar de ejecutar una sola instancia de cat
pasarle varios nombres de archivo que pueden ser ineficientes y pueden no tener el comportamiento que desea para algunos comandos (aunque está bien cat
). La sintaxis también es incómoda de escribir: debe escapar del punto y coma porque el punto y coma es especial para el shell.
Algunas versiones de find
(sobre todo la versión de GNU) permiten sustituir ;
con +
usar -exec
's añaden modo de correr menos casos de cat
:
find [whatever] -exec cat {} +
Esto pasará múltiples nombres de archivo a cada invocación de cat
, lo que puede ser más eficiente.
Sin embargo, tenga en cuenta que esto no garantiza el uso de una sola invocación. Si la línea de comando fuera demasiado larga, los argumentos se distribuirían entre múltiples invocaciones de cat
. Para cat
esto probablemente no es una gran cosa, pero para algunos otros comandos que esto puede cambiar el comportamiento de manera indeseable. En los sistemas Linux, el límite de longitud de la línea de comandos es bastante grande, por lo que la división en invocaciones múltiples es bastante rara en comparación con otros sistemas operativos.
El enfoque clásico / portátil es usar xargs
:
find [whatever] | xargs cat
xargs
ejecuta el comando especificado ( cat
en este caso) y agrega argumentos basados en lo que lee de stdin. Al igual que -exec
con +
, esto dividirá la línea de comandos si es necesario. Es decir, si find
produce demasiada salida, se ejecutará cat
varias veces. Como se mencionó en la sección -exec
anterior, hay algunos comandos donde esta división puede resultar en un comportamiento diferente. Tenga en cuenta que el uso xargs
como este tiene problemas con los espacios en los nombres de archivo, comoxargs
solo utiliza espacios en blanco como delimitador.
El método más robusto, portátil y eficiente también utiliza xargs
:
find [whatever] -print0 | xargs -0 cat
La -print0
bandera le dice find
que use \0
delimitadores (caracteres nulos) entre los nombres de archivo, y la -0
bandera le dice xargs
que espere estos \0
delimitadores. Esto tiene un comportamiento bastante idéntico al -exec
... +
enfoque, aunque es más portátil (pero desafortunadamente más detallado).
ls
.
$()
También funciona con comandos distintos de find
.
A mí me parece un trabajo para un script de shell:
for file in 'find -name *.xml'
do
grep 'hello' file
done
o algo así
El comando find tiene un argumento -exec que puede usar para cosas como esta, simplemente puede hacer grep directamente con eso.
Por ejemplo (a partir de aquí, otros buenos ejemplos en esta página ):
find . -exec grep "www.athabasca" '{}' \; -print
En bash, lo siguiente sería apropiado:
find /dir -type f -print0 | xargs -0i cat {} | grep whatever
Esto encontrará todos los archivos en el /dir
directorio y canalizará los nombres de los archivos de xargs
forma segura, lo que conducirá de manera segura grep
.
Omitir xargs
no es una buena idea si tiene muchos miles de archivos /dir
; cat
se romperá debido a la longitud excesiva de la lista de argumentos. xargs
lo resolverá todo por ti.
El -print0
argumento de find
mallas con el -0
argumento xargs
de manejar los nombres de archivo con espacios correctamente. El -i
argumento para le xargs
permite insertar el nombre del archivo donde sea necesario en la cat
línea de comando. Los corchetes se reemplazan por el nombre del archivo canalizado en el cat
comando desde find
.
Esto funciona para mi
find _CACHE_* | while read line; do
cat "$line" | grep "something"
done
Usa ggrep .
ggrep -H -R -I "mysearchstring" *
para buscar un archivo en Unix que contenga texto ubicado en el directorio actual o un subdirectorio
Esto imprimirá el nombre y el contenido de los archivos solo de forma recursiva.
find . -type f -printf '\n\n%p:\n' -exec cat {} \;
Editar (versión mejorada): Esto imprimirá el nombre y el contenido de los archivos de texto (ascii) solo de forma recursiva.
find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'
Un intento mas
find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;
¿Estás tratando de encontrar texto en archivos? Simplemente puede usar grep para eso ...
grep searchterm *
Para enumerar y ver el contenido de todos los archivos abc.def en un servidor en los directorios / ghi y / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;
Para enumerar los archivos abc.def que tienen entradas comentadas y mostrar, vea esas entradas en los directorios / ghi y / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
find -name '*.foo' -print
funcionó muy bien para mí ... Gracias