Cómo usar el comando de búsqueda en Linux

el linux find El comando es excelente para buscar archivos y directorios. Pero también puede pasar los resultados de la búsqueda a otros programas para su posterior procesamiento. Te mostramos cómo.

El comando de búsqueda de Linux

el linux find comando es potente y flexible. Puede buscar archivos y directorios utilizando una gran cantidad de criterios diferentes, no solo nombres de archivo. Para example, puede buscar archivos vacíos, archivos ejecutables o archivos propiedad de un usuario en particular. Puede encontrar y enumerar archivos por sus tiempos de acceso o modificación, puede usar patrones de expresiones regulares, es recursivo de forma predeterminada y funciona con pseudo-archivos como canalizaciones con nombre (búferes FIFO).

Todo eso es fantásticamente útil. el humilde find El comando realmente tiene algo de poder. Pero hay una manera de aprovechar ese poder y llevar las cosas a otro nivel. Si podemos tomar la salida del find comando y usarlo automáticamente como la entrada de otros comandos, podemos hacer que algo suceda con los archivos y directorios que encuentra para nosotros.

El principio de canalizar la salida de un comando a otro comando es una característica central de los sistemas operativos derivados de Unix. El principio de diseño de hacer que un programa haga una cosa y la haga bien, y esperar que su salida pueda ser la entrada de otro programa, incluso un programa aún no escrito, a menudo se describe como la “filosofía de Unix”. Y, sin embargo, algunas utilidades principales, como mkdir, no acepte entrada canalizada.

Para subsanar esta deficiencia el xargs El comando se puede usar para dividir la entrada canalizada y alimentarla en otros comandos como si fueran parámetros de línea de comando para ese comando. Esto logra casi lo mismo que una tubería sencilla. Eso es “casi lo mismo”, y no “exactamente lo mismo”, porque puede haber diferencias inesperadas con las expansiones de shell y la inclusión de nombres de archivo.

Uso de buscar con xargs

Nosotros podemos usar find con xargs a alguna acción realizada sobre los archivos que se encuentran. Esta es una manera larga de hacerlo, pero podríamos alimentar los archivos encontrados por find en xargs , que luego los canaliza a tar para crear un archivo de almacenamiento de esos archivos. Ejecutaremos este comando en un directorio que tiene muchos archivos PAGE del sistema de ayuda.

find ./ -name "*.page" -type f -print0 | xargs -0 tar -cvzf page_files.tar.gz

El comando se compone de diferentes elementos.

  • buscar ./ ​​-nombre “*.página” -tipo f -print0: La acción de búsqueda comenzará en el directorio actual, buscando por nombre los archivos que coincidan con la cadena de búsqueda “*.page”. Los directorios no aparecerán en la lista porque le indicamos específicamente que solo busque archivos, con -type f. El print0 el argumento dice find para no tratar los espacios en blanco como el final de un nombre de archivo. Esto significa que los nombres de archivo con espacios en ellos se procesarán correctamente.
  • xargs-o: El -0 argumentos xargs para no tratar los espacios en blanco como el final de un nombre de archivo.
  • tar -cvzf page_files.tar.gz: Este es el comando xargs va a alimentar la lista de archivos de find a. La utilidad tar creará un archivo de almacenamiento llamado “page_files.tar.gz”.


Nosotros podemos usar ls para ver el archivo de almacenamiento que se crea para nosotros.

ls *.gz

El archivo de almacenamiento creado al canalizar la salida de find a través de xargs y tar

El archivo de almacenamiento se crea para nosotros. Para que esto funcione, todos los nombres de archivo deben pasarse a tar en masa, que es lo que pasó. Todos los nombres de archivo fueron etiquetados al final de la tar comando como una línea de comando muy larga.

Puede elegir que el comando final se ejecute en todos los nombres de archivo a la vez o que se invoque una vez por nombre de archivo. Podemos ver la diferencia con bastante facilidad canalizando la salida de xargs a la utilidad de conteo de líneas y caracteres wc.

Este comando canaliza todos los nombres de archivo en wc En seguida. Efectivamente, xargs construye una larga línea de comando para wc con cada uno de los nombres de archivo en él.

find . -name "*.page" -type f -print0 | xargs -0 wc

Canalización de múltiples nombres de archivo a wc a la vez

Se imprimen las líneas, palabras y caracteres de cada archivo, junto con un total para todos los archivos.

Word  contar estadísticas para muchos archivos, con un total para todos los archivos


si usamos xarg‘s -I (reemplazar cadena) y definir un token de cadena de reemplazo, en este caso ” {}“—el token se reemplaza en el comando final por cada nombre de archivo a su vez. Esto significa wc se llama repetidamente, una vez para cada archivo.

find . -name "*.page" -type f -print0 | xargs -0 -I "{}" wc "{}"

Usando una cadena de reemplazo para enviar nombres de archivo a un wc uno a la vez

La salida no está bien alineada. Cada invocación de wc opera en un solo archivo por lo que wc no tiene nada con lo que alinear la salida. Cada línea de salida es una línea de texto independiente.

Salida de múltiples invocaciones de wc

Porque wc solo puede proporcionar un total cuando opera en varios archivos a la vez, no obtenemos las estadísticas de resumen.

La opción find -exec

El find El comando tiene un método incorporado para llamar a programas externos para realizar un procesamiento adicional en los nombres de archivo que devuelve. El -exec (ejecutar) tiene una sintaxis similar pero diferente de la xargs mando.

find . -name "*.page" -type f -exec wc -c "{}" ;

Usando -exec para enviar nombres de archivos individuales a wc

Esto contará las palabras en los archivos coincidentes. El comando se compone de estos elementos.

  • encontrar .: Inicie la búsqueda en el directorio actual. El find El comando es recursivo de forma predeterminada, por lo que también se buscarán los subdirectorios.
  • -nombre “*.página”: Estamos buscando archivos con nombres que coincidan con la cadena de búsqueda “*.page”.
  • -tipo f: Solo buscamos archivos, no directorios.
  • -wc ejecutivo: Vamos a ejecutar el wc comando en los nombres de archivo que coinciden con la cadena de búsqueda.
  • -w: Cualquier opción que desee pasar al comando debe colocarse inmediatamente después del comando.
  • “{}”: El marcador de posición “{}” representa cada nombre de archivo y debe ser el último elemento en la lista de parámetros.
  • ;: un punto y coma “;” se utiliza para indicar el final de la lista de parámetros. Debe escaparse con una barra invertida “” para que el shell no lo interprete.

Cuando ejecutamos ese comando, vemos la salida de wc. El -c (recuento de bytes) limita su salida al número de bytes en cada archivo.

El resultado de usar -exec para enviar muchos nombres de archivo únicos a wc


Como se puede ver no hay total. El wc El comando se ejecuta una vez por nombre de archivo. Sustituyendo un signo más “+” para el punto y coma final “;” podemos cambiar -execEl comportamiento de operar en todos los archivos a la vez.

find . -name "*.page" -type f -exec wc -c "{}" +

Usando -exec para enviar todos los nombres de archivo a wc a la vez

Obtenemos el resumen total y los resultados claramente tabulados que nos dicen que todos los archivos se pasaron a wc como una larga línea de comando.

Resultado del uso de -exec para enviar todos los nombres de archivo a wc a la vez

ejecutivo realmente significa ejecutivo

El -exec La opción (ejecutar) no inicia el comando ejecutándolo en el shell actual. Utiliza el sistema integrado de Linux exec para ejecutar el comando, reemplazando el proceso actual, su shell, con el comando. Entonces, el comando que se inicia no se ejecuta en absoluto en un shell. Sin un shell, no puede obtener la expansión de shell de comodines, y no tiene acceso a alias y funciones de shell.

Esta computadora tiene una función de shell definida llamada words-only. Esto cuenta solo las palabras en un archivo.

function words-only () 
{ 
  wc -w $1
}

Quizás una función extraña, “solo palabras” es mucho más largo de escribir que “wc -w”, pero al menos significa que no necesita recordar las opciones de la línea de comandos para wc. Podemos probar lo que hace así:

words-only user_commands.pages

Usando una función de shell para contar las palabras en un solo archivo

Eso funciona bien con una invocación de línea de comandos normal. Si tratamos de invocar esa función usando find‘s -exec opción, fallará.

find . -name "*.page" -type f -exec words-only "{}" ;

Intentando usar una función de shell con -exec


El find comando no puede encontrar la función de shell, y el -exec la acción falla.

-exec no pudo encontrar la función de shell, debido a que find no se ejecuta en un shell

Para superar esto podemos tener find inicie un shell Bash y pásele el resto de la línea de comando como argumentos al shell. Necesitamos envolver la línea de comando entre comillas dobles. Esto significa que debemos escapar de las comillas dobles que están alrededor del “{}” reemplazar cadena.

Antes de que podamos ejecutar el find comando, necesitamos exportar nuestra función de shell con el -f (como una función) opción:

export -f words-only
find . -name "*.page" -type f -exec bash -c "words-only "{}"" ;

Uso de find para iniciar un shell para ejecutar la función de shell en

Esto funciona como se esperaba.

La función de shell que se llama en un nuevo shell

Usar el nombre de archivo más de una vez

Si desea encadenar varios comandos, puede hacerlo y puede usar el botón “{}” reemplazar cadena en cada comando.

find . -name "*.page" -type f -exec bash -c "basename "{}" && words-only "{}"" ;

Si nosotros cd subir un nivel fuera del directorio “páginas” y ejecutar ese comando, find seguirá descubriendo los archivos PAGE porque busca recursivamente. El nombre del archivo y la ruta se pasan a nuestro words-only funcionar igual que antes. Puramente por razones de demostración usando -exec con dos comandos, también estamos llamando al basename comando para ver el nombre del archivo sin su ruta.

Ambos basename comando y el words-only función de shell tienen los nombres de archivo pasados ​​a ellos usando un “{}” reemplazar cadena.

Llamar al comando basename y la función de shell de solo palabras desde la misma llamada -exec

Caballos de carreras

Hay una carga de CPU y una penalización de tiempo por llamar repetidamente a un comando cuando podría llamarlo una vez y pasarle todos los nombres de archivo de una sola vez. Y si está invocando un nuevo shell cada vez que ejecuta el comando, la sobrecarga empeora.


Pero a veces, dependiendo de lo que intente lograr, es posible que no tenga otra opción. Cualquiera que sea el método que requiera su situación, nadie debería sorprenderse de que Linux proporcione suficientes opciones para que pueda encontrar la que se adapte a sus necesidades particulares.

Related Posts