Existe una opción que grep -f MY_FILE
le permite buscar patrones tomados de un archivo, en lugar de especificarlos directamente en la línea de comando.
¿Existe una opción para hacer algo similar con el find
comando y dejar que lea los patrones para buscar desde un archivo de entrada?
Respuesta1
find
no parece tener tales capacidades integradas, pero puede usarlas xargs
para construir múltiples find
comandos usando argumentos de un archivo, como:
xargs -a patterns.txt -I% find Pictures/ -name %
donde patterns.txt
estaría una lista de patrones adecuados para el -name
filtro, un patrón por línea. Preste atención a que no tenga espacios iniciales o finales allí, ya que estarían incluidos en el patrón. Un ejemplo:
*.jpg
2018-06-*
*foo*
unicorn.png
Nota:Si bien esta respuesta parece bastante fácil y elegante, en los comentarios se señaló correctamente que tiene algunas desventajas:
El rendimiento no es demasiado bueno para carpetas grandes o muchos patrones, ya que se ejecutará
find
una vez por patrón en su archivo, lo que hará que explore repetidamente toda la carpeta de búsqueda.Por eso, también si tiene varios patrones que potencialmente podrían superponerse (como
*.jpg
y*foo*
), los archivos que coincidan con más de un patrón aparecerán tantas veces en el resultado. Si de todos modos solo está imprimiendo los nombres, puede canalizar la salidasort -u
para eliminar duplicados, pero si, por ejemplo, elimina esos resultados o ejecuta algún-exec
comando en ellos, esto puede ser menos deseable.Si alguna de estas desventajas es un problema para su caso de uso, tal vez sea mejor optar por una de las respuestas alternativas.
Explicación del comando:
xargs
leerá una lista de argumentos y los usará para construir y ejecutar una nueva línea de comando.-a patterns.txt
le dice que lea ese archivo en lugar de la entrada estándar.-I%
le dice que no simplemente agregue los argumentos que leyó al final de la línea de comando, sino que reemplace el%
carácter en la línea de comando que proporcionó con un argumento. Esto implica crear y ejecutar un comando separado por argumento de entrada.find Pictures/ -name %
es la línea de comando en la que queremos insertar los argumentos, reemplazando el%
. No es necesario citarlo aquí, porquexargs
se asegurará de que cada argumento que inserte se trate como un token único y no se divida por sí solo. Por supuesto, puede reemplazarPictures/
con su propio directorio de búsqueda y también usar filtros diferentes o más además de-name
. Debido a que usamos la opción de inserción, también puede agregar acciones como-exec ...
al final del comando.
Respuesta2
Simplemente puede crear una expresión regular a partir del contenido de su archivo usando paste -sd'|' bar
.
find ~/foo -regextype egrep -regex "^.*/($(paste -sd'|' bar))$"
La expresión regular será"^.*/(a|b)$"
Respuesta3
No muy recientemente, hice unrespuestaque combina múltiples patrones usando -regex
flag en find
. En base a eso, podemos crear un pequeño script o función para hacer el mismo trabajo, pero construyendo la lista de patrones a partir del archivo.
#!/bin/bash
read_file(){
local full_pattern=""
while IFS= read -r pattern; do
if [ -z "$full_pattern" ];then
full_pattern="$pattern"
continue
fi
full_pattern="$full_pattern\|$pattern"
done < "$1"
echo "$full_pattern"
}
fp=$(read_file "$1" )
find "$2" -type f -regex ".*\($fp\).*$"
Qué hace esto:
- llamamos script as
findf.sh input.txt /etc
, donde el primer parámetro posicional es el archivo con patrones y el segundo, el directorio donde buscar. GNU find asume.
el directorio si se omite el argumento del directorio, por lo que$2
no es necesario. - La función
read_file
lee el archivo de entrada que es el primer parámetro posicional del script. Esto crea un patrón para-regex
la bandera. - Este patrón se repite en el bloque "principal" del script, se guarda en
fp
una variable y se pasa alfind
comando.