El comando de búsqueda de Linux es excelente para encontrar archivos y directorios. Sin embargo, también puede transferir los resultados de la búsqueda a otros programas para su posterior procesamiento. Le mostraremos cómo.
El comando de búsqueda de Linux
Tabla de contenidos
El comando de búsqueda de Linux es poderoso y flexible. Puede buscar archivos y directorios utilizando una variedad de criterios, no solo nombres de archivos. Por ejemplo, puede buscar archivos vacíos, archivos ejecutables o archivos propiedad de un usuario específico. Puede buscar y enumerar archivos en función de los tiempos de acceso o modificación, puede usar patrones de expresiones regulares, es recursivo de forma predeterminada y funciona con pseudoarchivos como canalizaciones con nombre (búfer FIFO).
Todo esto es increíblemente útil. El comando humilde que encuentra realmente tiene poder. Pero hay una manera de aprovechar ese poder y llevar las cosas a otro nivel. Si podemos tomar la salida del comando de búsqueda y usarla automáticamente como entrada para otros comandos, podemos hacer algo con los archivos y directorios que encuentren el descubrimiento por nosotros.
El principio de redirigir la salida de un comando a otro comando es una característica fundamental 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 sea la entrada de otro programa, incluso un programa no escrito, a menudo se denomina «filosofía Unix». Sin embargo, algunas utilidades básicas como mkdir no aceptan entradas canalizadas.
Para superar esta deficiencia, el comando xargs se puede usar para analizar la entrada enviada a través de canalizaciones y pasarla a otros comandos como si fueran parámetros de línea de comando para ese comando. Esto se logra casi como con una tubería simple. Es «casi lo mismo» y no «exactamente lo mismo» porque puede haber diferencias inesperadas en las extensiones de shell y la sustitución de nombres de archivo.
Usando la búsqueda con xargs
Podemos usar find con xargs para ciertas acciones realizadas en archivos encontrados. Es un método tedioso, pero podríamos colocar los archivos encontrados por find en xargs, que luego los redirige a tar para crear un archivo de esos archivos. Ejecutamos este comando en un directorio que contiene muchos archivos PAGE del sistema de ayuda.
encontrar ./ -nombre «* .página» -tipo f -print0 | xargs -0 tar -cvzf archivo de intercambio.tar.gz
El pedido se compone de varios elementos.
- buscar ./ -nombre «* .página» -tipo f -print0: La acción de búsqueda comienza en el directorio actual y busca por nombre los archivos que coincidan con la cadena de búsqueda «* .page». Los directorios no se enumeran porque decimos específicamente buscar solo archivos, con -type F. El argumento print0 le dice a find que no trate los espacios como el final de un nombre de archivo. Esto significa que los nombres de archivo con espacios se manejan correctamente.
- xargs-o: Los argumentos -0 xargs no consideran los espacios como el final de un nombre de archivo.
- tar -cvzf archivos_pagina.tar.gz: Este es el comando que usará xargs para completar la lista de archivos desde buscar hasta. La utilidad tar crea un archivo de almacenamiento llamado page_files.tar.gz.
Podemos usar ls para ver el archivo de almacenamiento creado 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 de forma masiva, lo que ha sucedido. Todos los nombres de archivo se han marcado como una línea de comando muy larga al final del comando tar.
Puede optar por ejecutar el último comando para todos los nombres de archivo a la vez o ejecutarlo una vez por nombre de archivo. Podemos notar fácilmente la diferencia vinculando la salida de xargs a la línea wc y la utilidad de conteo de caracteres.
Este comando dirigirá todos los nombres de archivo a wc al mismo tiempo. De hecho, xargs crea una larga línea de comando para wc con cada uno de los nombres de archivo que contiene.
Encontrar . -nombre «* .página» -tipo f -print0 | xargs -0 WC
Las líneas, palabras y caracteres de cada archivo se imprimen con un total para todos los archivos.
Si usamos la opción -I (Reemplazar cadena) de xarg y configuramos un token de cadena de reemplazo, en este caso «{}», el token en el último comando se reemplazará con cada nombre de archivo a su vez. Esto significa que wc se llama repetidamente, una vez para cada archivo.
Encontrar . -nombre «* .página» -tipo f -print0 | xargs -0 -I «{}» wc «{}»
La salida está desalineada. Cada invocación de wc opera en un solo archivo, por lo que wc no tiene nada con lo que reconciliar la salida. Cada línea de salida es una línea de texto independiente.
Dado que wc solo puede devolver un total general cuando se trabaja con varios archivos al mismo tiempo, no obtenemos estadísticas de resumen.
La opción encuentra -exec
El comando de búsqueda tiene un método incorporado para llamar a programas externos para procesar aún más los nombres de archivo que devuelve. La opción -exec (ejecutar) tiene una sintaxis similar al comando xargs, pero es diferente.
Encontrar . -nombre «* .página» -tipo f -exec wc -c «{}» ;
Esto contará las palabras en los archivos correspondientes. El comando consta de estos elementos.
- Encontrar .: inicia la búsqueda en el directorio actual. El comando Buscar es recursivo de forma predeterminada, por lo que también se buscan en los subdirectorios.
- -Nombre «* .Página»: Estamos buscando archivos cuyos nombres coincidan con la cadena de búsqueda «* .page».
- -Tipo F: Solo buscamos archivos, no directorios.
- – inodoros direccionales: ejecutamos el comando wc 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 este comando, vemos la salida de wc. El -c (número de bytes) limita su salida al número de bytes en cada archivo.
Como puedes ver, no hay suma. El comando wc se ejecuta una vez por nombre de archivo. Reemplazando el punto y coma final «;» con un signo más «+», podemos cambiar el comportamiento de -exec para procesar todos los archivos a la vez.
Encontrar . -nombre «* .página» -tipo f -exec wc -c «{}» +
Obtenemos el resumen total y los resultados cuidadosamente tabulados, que nos dicen que todos los archivos se han pasado a wc en una línea de comando larga.
ejecutivo realmente significa ejecutivo
La opción -exec (ejecutar) no inicia el comando ejecutándolo en el shell actual. Utiliza el inexec incorporado de Linux para ejecutar el comando y reemplaza el proceso actual, su shell, con el comando. Por lo tanto, el comando lanzado no se ejecuta en absoluto en un shell. Sin un shell, no puede obtener una extensión de shell comodín y no tiene acceso a los alias y funciones del shell.
Esta computadora tiene una función de shell llamada sólo palabras. Esto solo cuenta las palabras en un archivo.
solo palabras de función () {wc -w $ 1}
Quizás una característica extraña, «solo palabras» es mucho más largo de escribir que «wc -w», pero al menos significa que no tiene que recordar las opciones de línea de comando para wc. Podemos probar lo que hace así:
solo las palabras user_commands.pages
Funciona bien con una llamada de línea de comando normal. Si intentamos llamar a esta función con la opción -exec de find, falla.
Encontrar . -name «* .page» -type f -exec solo palabras «{}» ;
El comando de búsqueda no encuentra la función de shell y la acción -exec falla.
Como solución alternativa, podemos iniciar un shell bash y pasar el resto de la línea de comando al shell como argumentos. Necesitamos encerrar la línea de comando entre comillas. Esto significa que debemos evitar las comillas alrededor de la cadena de reemplazo «{}».
Antes de que podamos ejecutar el comando de búsqueda, necesitamos exportar nuestra función de shell con la opción -f (como una función):
export -f busca solo palabras. -name «* .page» -type f -exec bash -c «words only » {} «» ;
Funciona como se esperaba.
Usar el nombre del archivo más de una vez
Si desea concatenar varios comandos, puede hacerlo y puede reemplazar la cadena «{}» en cada comando.
Encontrar . -name «* .page» -type f -exec bash -c «nombre base» {} «&& solo palabras» {} «» ;
Si subimos un nivel desde el directorio «pages» y ejecutamos este comando, find aún encuentra los archivos PAGE porque realiza una búsqueda recursiva. El nombre del archivo y la ruta se pasan a nuestra función de todas las palabras como antes. Solo para demostrar el uso de -exec con dos comandos, también invocaremos el comando basename para mostrar el nombre del archivo sin su ruta.
El comando basename y la función de shell de todas las palabras reciben nombres de archivo con una cadena de reemplazo «{}».
carreras de caballos
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 a la vez. Y si invoca un nuevo shell cada vez que inicia el comando, la sobrecarga empeora.
Pero a veces, dependiendo de lo que quieras lograr, es posible que no tengas otras opciones. Cualquiera que sea el método que requiera su situación, nadie debería sorprenderse de que Linux ofrezca suficientes opciones para encontrar el que se adapte a sus necesidades particulares.