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
. Elprint0
el argumento dicefind
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
argumentosxargs
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 defind
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 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
Se imprimen las líneas, palabras y caracteres de cada archivo, junto 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 "{}"
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.
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 "{}" ;
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.
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 -exec
El comportamiento de operar en todos los archivos a la vez.
find . -name "*.page" -type f -exec wc -c "{}" +
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.
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
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 "{}" ;
El find
comando no puede encontrar la función de shell, y el -exec
la acción falla.
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 "{}"" ;
Esto funciona como se esperaba.
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.
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.