2011-05-31 17 views
12

Estoy trabajando en Linux & bash (o Cygwin & bash).Unix find: lista de archivos de stdin

Tengo una enorme-- enorme --estructura del directorio, y tengo que encontrar algunas agujas en el pajar.

Específicamente, estoy buscando estos archivos (20 o más):

foo.c 
bar.h 
... 
quux.txt 

Yo sé que ellos están en un subdirectorio en algún lugar bajo ..

Sé que puedo encontrar cualquiera de ellos con find . -name foo.c -print. Este comando toma unos minutos para ejecutarse.

¿Cómo puedo imprimir los nombres de estos archivos con su nombre de directorio completo? No quiero ejecutar 20 por separado find s - llevará demasiado tiempo.

¿Puedo dar a find la lista de archivos de stdin? ¿De un archivo? ¿Hay un comando diferente que hace lo que quiero?

¿Tengo que armar primero una línea de comando para find con -o usando un bucle o algo así?

Respuesta

11

Si la estructura de directorios es enorme, pero no cambiar con frecuencia, es bueno para correr

cd /to/root/of/the/files 
find . -type f -print > ../LIST_OF_FILES.txt #and sometimes handy the next one too 
find . -type d -print > ../LIST_OF_DIRS.txt 

después de que se puede encontrar algo muy rápido (con grep, sed, etc ..) y actualizar el Archivo- enumera solo cuando se cambia el árbol.(Es un reemplazo simplificado si usted no tiene locate)

Así,

grep '/foo.c$' LIST_OF_FILES.txt #list all foo.c in the tree.. 

Cuando quieren encontrar una lista de archivos, puede intentar lo siguiente:

fgrep -f wanted_file_list.txt < LIST_OF_FILES.txt 

o directamente con el comando find

find . type f -print | fgrep -f wanted_file_list.txt 

la -f para la media fgrep - leer golpeteo ns desde el archivo, por lo que puede agrupar fácilmente la entrada para varios patrones ...

1
+0

Y una vez que guardar la lista de archivos en una array, use un loop para construir el comando find? ¿Cuál es la mejor línea de comando para usar, dadas las circunstancias? – JXG

+0

No necesita colocar los archivos en una matriz; simplemente crea directamente el comando find en una matriz y luego llámalo. –

+0

er, ¿cómo lo haces, exactamente? – JXG

3

No debería necesitar ejecutar find veinte veces.

Puede generar un solo comando con un múltiplo de especificadores de nombre de archivo:

find . \(-name 'file1' -o -name 'file2' -o -name 'file3' \) -exec echo {} \; 
+0

-exec echo {} \; no es necesario. – akond

+0

Sí, gracias, pero estoy acostumbrado a una versión que no es GNU de 'encontrar', así que tiendo a ser explícito. Y si el 'echo' se reemplaza con, por ejemplo,' printf' podemos tener mucho más control de la salida. – pavium

+0

Entonces, si hay 20 de estos archivos ¿no hay otra alternativa que escribir '-o -name' 20 veces? Eso no aprovecha la entrada de tubería de stdin o de un archivo. –

2

es el comando locate(1) una respuesta aceptable? Todas las noches se construye un índice, y se puede consultar el índice bastante rapidez:

$ time locate id_rsa 
/home/sarnold/.ssh/id_rsa 
/home/sarnold/.ssh/id_rsa.pub 

real 0m0.779s 
user 0m0.760s 
sys 0m0.010s 

renuncié a la ejecución de un comando similar find en mi directorio personal a los 36 segundos. :)

Si todas las noches no funciona, puede ejecutar manualmente el programa updatedb(8) antes de ejecutar locate(1) consultas. /etc/updatedb.conf (updatedb.conf(5)) le permite seleccionar directorios específicos o tipos de sistemas de archivos para incluir o excluir.

+0

Esto hace en principio lo que quiero hacer, y para obtener exactamente lo que quiero puedo grep para mi directorio deseado, pero todas las noches no funciona, y no tengo permisos para 'updatedb'. – JXG

+0

@JXG, no pase por alto la sección 'EJEMPLOS' de la página de manual :) _Para crear una base de datos de mlocate privada como un usuario que no sea root, ejecute_' updatedb -l 0 -o archivo_db -U directorio_origen'. – sarnold

+0

ja ja, no tengo esa sección en la página de manual de mi sistema. – JXG

0

Aquí hay una manera de procesar una lista de archivos de stdin y ensamblar el comando (FreeBSD) find para usar la expresión extendida extendida que coincida con (n1|n2|n3).

para GNU encontrar puede que tenga que utilizar una de las siguientes opciones para activar extendida expresiones regulares:

-regextype posix-egrep

-regextype posix-extended

echo ' 
foo\\.c 
bar\\.h 
quux\\.txt 
' | xargs bash -c ' 
IFS="|"; 
find -E "$PWD" -type f -regex "^.*/($*)$" -print 
echo find -E "$PWD" -type f -regex "^.*/($*)$" -print 
' arg0 

# note: "$*" uses the first character of the IFS variable as array item delimiter 
(
IFS='|' 
set -- 1 2 3 4 5 
echo "$*" # 1|2|3|4|5 
) 
Cuestiones relacionadas