Estoy tratando de ejecutar un find
comando para todos los archivos JavaScript, pero ¿cómo excluyo un directorio específico?
Aquí está el find
código que estamos usando.
for file in $(find . -name '*.js')
do
java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done
find ... | while read -r file ...
. Además, es mejor aceptar y votar las respuestas.for file in $(find .); do echo "$file"; done
. Los nombres con espacios están divididos, lo que no queremos.Respuestas:
Usa el
-prune
interruptor. Por ejemplo, si desea excluir elmisc
directorio, simplemente agregue un-path ./misc -prune -o
a su comando de búsqueda:Aquí hay un ejemplo con múltiples directorios:
Aquí excluimos dir1 , dir2 y dir3 , ya que en las
find
expresiones es una acción que actúa según los criterios-path dir1 -o -path dir2 -o -path dir3
(si dir1 o dir2 o dir3 ), AND contype -d
.Otra acción es
-o print
, solo imprimir.fuente
-print
(o cualquier otra acción) explícitamente después-name
. En ese caso, ambos "lados" de-o
la impresión finalizan, mientras que si lo usa-print
, solo se imprime ese lado.Because -delete implies -depth, you cannot usefully use -prune and -delete together.
Entonces, ¿cómo hago para eliminar con find si deseo excluir directorios específicos de la eliminación?find . -not -path "./.git*"
. El uso en./dir*
lugar de./dir/*
elimina el directorio y los contenidos de la salida.Si
-prune
no funciona para usted, esto:Advertencia: requiere atravesar todos los directorios no deseados.
fuente
-prune
no excluye el directorio en sí, excluye su contenido, lo que significa que obtendrá una línea no deseada en la salida con el directorio excluido..
a*
. asífind -name "*.js" -not -path "*/omitme/*"
que omitiría archivos de un directorio llamado "omitme" en cualquier nivel de profundidad.-print
explícitamente.Encuentro lo siguiente más fácil de razonar que otras soluciones propuestas:
Nota importante: las rutas que escriba después
-path
deben coincidir exactamente con lo quefind
se imprimiría sin la exclusión. Si esta frase confunde que sólo asegúrese de usar rutas completas en todo el conjunto de comandos de esta manera: . Consulte la nota [1] si desea una mejor comprensión.find /full/path/ -not \( -path /full/path/exclude/this -prune \) ...
En el interior
\(
y\)
es una expresión que se ajuste exactamentebuild/external
(ver nota importante más arriba), y la voluntad, en caso de éxito, evitar el desplazamiento nada por debajo . Esto se agrupa como una sola expresión con el paréntesis escapado, y con el prefijo-not
que haráfind
omitir todo lo que coincida con esa expresión.Uno podría preguntar si agregar
-not
no hará que todos los demás archivos estén ocultos por-prune
reaparecer, y la respuesta es no. La manera-prune
funciona es que todo lo que, una vez alcanzado, los archivos debajo de ese directorio se ignoran permanentemente.Esto proviene de un caso de uso real, donde necesitaba llamar a yui-compressor en algunos archivos generados por wintersmith, pero omitir otros archivos que deben enviarse tal cual.
Nota [1] : Si desea excluir
/tmp/foo/bar
y ejecuta find como este "find /tmp \(...
", debe especificarlo-path /tmp/foo/bar
. Si, por otro lado, ejecuta find como estecd /tmp; find . \(...
, debe especificarlo-path ./foo/bar
.fuente
find . -not \( -path ./CVS -prune \) -type f -mtime +100 -delete find: The -delete action atomatically turns on -depth, but -prune does nothing when -depth is in effect. If you want to carry on anyway, just explicitly use the -depth option.
-exec rm -rf {} \;
lugar de-delete
.find
, esto es realmente obvio, pero me hizo tropezar. Si usted está buscando en el directorio actual (especificando.
como la ruta de búsqueda, o no especifica ninguno en absoluto), lo más probable es que su patrón después de-path
empezar con./
, por ejemplo:find -not \( -path ./.git -prune \) -type f
.find searchdir \! \( -type d \( -path './excludedir/*' -o -path './excludedir2/*' -o -path './excludedir3/*' \) -prune \)
seguida de cualquier condición que coincida con lo que está buscando.Claramente, aquí existe cierta confusión sobre cuál debería ser la sintaxis preferida para omitir un directorio.
Opinión de GNU
Desde la página de manual de encontrar de GNU
Razonamiento
-prune
dejafind
de descender a un directorio. Solo especificar-not -path
seguirá descendiendo al directorio omitido , pero-not -path
será falso cada vezfind
pruebe cada archivo.Problemas con
-prune
-prune
hace lo que está destinado a hacer, pero aún hay algunas cosas que debe tener en cuenta al usarlo.find
imprime el directorio podado.-prune
solo funciona con-print
y no otras acciones.-prune
funciona con cualquier acción excepto-delete
. ¿Por qué no funciona con eliminar? Para-delete
trabajar, find necesita atravesar el directorio en orden DFS, ya-delete
que primero eliminará las hojas, luego los padres de las hojas, etc. Pero para especificar-prune
que tiene sentido,find
debe presionar un directorio y dejar de descender, lo que claramente no tiene sentido con-depth
o-delete
sobre.Actuación
Configuré una prueba simple de las tres respuestas más votadas sobre esta pregunta (reemplazada
-print
por-exec bash -c 'echo $0' {} \;
para mostrar otro ejemplo de acción). Los resultados están abajoConclusión
Tanto la sintaxis de f10bit y la sintaxis de Daniel C. Sobral tomaron 10-25ms para funcionar en promedio. La sintaxis de GetFree , que no usa
-prune
, tomó 865 ms. Entonces, sí, este es un ejemplo bastante extremo, pero si le importa el tiempo de ejecución y está haciendo algo remotamente intensivo, debe usar-prune
.Tenga en cuenta que la sintaxis de Daniel C. Sobral fue la mejor de las dos
-prune
sintaxis; pero, sospecho fuertemente que esto es el resultado de un cierto almacenamiento en caché, ya que cambiar el orden en que se ejecutaron los dos dio como resultado el resultado opuesto, mientras que la versión sin poda siempre fue la más lenta.Script de prueba
fuente
-prune
, puedo decir que rara vez hay alguna diferencia. Tenga en cuenta que el comando que comience primero se beneficiará del rendimiento de la CPU, el calentamiento posterior de la CPU> la caída del rendimiento causará una desaceleración menor (purgué el caché antes de cada comando como sugerencia de @ndemou)name1() name2() name3()
en el script de prueba @BroSlow anterior para cambiar el orden de ejecución y obtener una visión de lo que dije. Sin embargo, en la vida real es imperceptible entre esos dos.Este es el único que funcionó para mí.
Buscando "MyFile" excluyendo "Directorio". Dar énfasis a las estrellas *.
fuente
! -path '*/Directory/*'
a su comando en sucesión para ignorar múltiples directoriosdocker container
solo funciona consh -c "find..."
Una opción sería excluir todos los resultados que contienen el nombre del directorio con grep. Por ejemplo:
fuente
-prune
), no.find . -name '*.js' | grep -v excludeddir | grep -v excludedir2 | grep -v excludedir3
pero puede haber alguna manera grep.egrep -v '(dir1|dir2|dir3)'
. Sin embargo, en este caso de estudio específico, sería mejor excluir directorios dentro defind
sí mismo.Prefiero la
-not
notación ... es más legible:fuente
find
dice: "Para ignorar un directorio y los archivos que se encuentran debajo, use -prune".find . -iname '*' -and -not -path './somePath'
no evita que ingrese a dicho directorio.find . -iname '*' -not -path './.git/*'
find . -not -path "*/.git*"
sería lo que quieres.Use la opción -prune. Entonces, algo como:
El '-type d -name proc -prune' solo busca directorios llamados proc para excluir.
El '-o' es un operador 'OR'.
fuente
-print
al final puede mejorar los resultados.find . -type d -name .hg -prune -o -name data
ignoró el contenido de los.hg
directorios (múltiples) , pero enumeró los.hg
directorios en sí. Con-print
, solo enumeraba los directorios de "datos" que estaba buscando.-prune
definitivamente funciona y es la mejor respuesta porque evita descender al directorio que desea excluir.-not -path
que aún busca el directorio excluido, simplemente no imprime el resultado, lo que podría ser un problema si el directorio excluido está montado en el volumen de la red o no tiene permisos.La parte difícil es que
find
es muy particular sobre el orden de los argumentos, por lo que si no los entiende correctamente, es posible que su comando no funcione. El orden de los argumentos es generalmente como tal:{path}
: Ponga todos los argumentos relacionados con la ruta primero, como. -path './dir1' -prune -o
{options}
: Tengo el mayor éxito al poner-name, -iname, etc
como última opción en este grupo. P.ej-type f -iname '*.js'
{action}
: Querrás agregar-print
cuando uses-prune
Aquí hay un ejemplo de trabajo:
fuente
Este es el formato que utilicé para excluir algunas rutas:
Usé esto para encontrar todos los archivos que no están en las rutas ". *":
fuente
El enfoque -path -prune también funciona con comodines en la ruta. Aquí hay una declaración find que encontrará los directorios para un servidor git que sirve a múltiples repositorios git que dejan fuera los directorios internos de git:
fuente
Para excluir múltiples directorios:
Para agregar directorios, agregue
-o -path "./dirname/*"
:Pero tal vez debería usar una expresión regular , si hay muchos directorios para excluir.
fuente
Hay muchas buenas respuestas, solo me llevó un tiempo entender para qué era cada elemento del comando y la lógica detrás de él.
find comenzará a buscar archivos y directorios en el directorio actual, de ahí el
find .
.La
-o
opción representa un OR lógico y separa las dos partes del comando:Cualquier directorio o archivo que no sea el directorio ./misc no pasará la primera prueba
-path ./misc
. Pero serán probados contra la segunda expresión. Si su nombre corresponde al patrón*.txt
que imprimen, debido a la-print
opción.Cuando find alcanza el directorio ./misc, este directorio solo satisface la primera expresión. Entonces
-prune
se le aplicará la opción. Le dice al comando find que no explore ese directorio. Por lo tanto, cualquier archivo o directorio en ./misc ni siquiera será explorado por find, no se probará con la segunda parte de la expresión y no se imprimirá.fuente
Para una solución de trabajo (probado en Ubuntu 12.04 (Precise Pangolin)) ...
buscará archivos MP3 en la carpeta y subcarpetas actuales, excepto en la subcarpeta dir1.
Utilizar:
... para excluir dir1 Y dir2
fuente
un buen truco para evitar imprimir los directorios podados es usar
-print
(funciona-exec
también) después del lado derecho del-or
after-prune
. Por ejemplo, ...imprimirá la ruta de todos los archivos debajo del directorio actual con la extensión '.j2 ", omitiendo todos los directorios ocultos. Neat. Pero también imprimirá la impresión de la ruta completa de cada directorio que se omite, como se indicó anteriormente. Sin embargo, el siguiente no, ...
porque lógicamente hay un oculto
-and
después del-iname
operador y antes de la impresión. Esto lo une a la parte derecha de la-or
cláusula debido al orden booleano de operaciones y asociatividad. Pero los documentos dicen que hay un oculto-print
si no-print0
está especificado (o alguno de sus primos ... , etc.). Entonces, ¿por qué no está la parte izquierda de la-or
impresión? Aparentemente (y no entendí esto desde mi primera lectura de la página del manual), eso es cierto si no hay-print
-o-exec
EN CUALQUIER LUGAR, en cuyo caso, -print se rocía lógicamente para que todo se imprima. Si incluso UNOprint
operación estilo expresada en alguna cláusula, todos esos lógicos ocultos desaparecen y obtienes solo lo que especificas. Ahora, francamente, podría haberlo preferido al revés, pero luegofind
operador con solo operadores descriptivos aparentemente no haría nada, así que supongo que tiene sentido. Como se mencionó anteriormente, todo esto también funciona-exec
, por lo que a continuación se ofrece unals -la
lista completa de cada archivo con la extensión deseada, pero no se enumera el primer nivel de cada directorio oculto, ...Para mí (y para otros en este hilo), la
find
sintaxis se vuelve bastante barroca con bastante rapidez, por lo que siempre agrego parens para asegurarme de saber qué se une a qué, por lo que generalmente creo una macro para la capacidad de escritura y formulo todas las declaraciones como. ..Es difícil equivocarse configurando el mundo en dos partes de esta manera. Espero que esto ayude, aunque parece poco probable que alguien lea la respuesta número 30 y la vote, pero uno puede esperar. :-)
fuente
Puede usar la opción de podar para lograr esto. Como en por ejemplo:
O la opción inversa grep "grep -v":
Puede encontrar instrucciones detalladas y ejemplos en el comando de búsqueda de Linux para excluir directorios de la búsqueda .
fuente
find . -type f -print -o -path "*/node_modules" -prune
... usando el comodín esto omite "node_modules" en cualquier nivel; el uso-print
en la primera alternativa-type f -print
solo imprime esa parte, por lo que los directorios "node_modules" no están en la lista. (También se puede invertir:find . -path "*/node_modules" -prune -o -type f -print
)./node_modules
y*/node_modules
de él. Para mi caso, dondenode_modules
solo existe en el directorio en el que comienzo la búsqueda (y debajo de esenode_modules
directorio), puedo usarlofind . -type f -print -o -path "./node_modules" -prune
porque no habrá unnode_modules
directorio en ningún otro directorio.node_modules
subdirectorio, pero también había subdirectorios que tenían sus propios node_modules ... utilizando./node_modules
coincidencias solo con el subdirectorionode_modules
bajo el directorio actual.
y lo poda; usando*/node_modules
coincidencias y poda el directorio a cualquier profundidad, ya que*
as como un globo coincide con cualquier prefijo de ruta principal, como./test5/main/node_modules
no solo el./
prefijo. El*
es un comodín, pero como un globo no como una expresión regular.fuente
find ~/Projects -name '*.js' -\! -name 'node_modules' -prune
sigue apareciendo archivosnode_modules
en su caminofind ~/Projects -path ~/Projects/node_modules -prune -o -name '*.js' -print
. El nombre de esa ruta debe coincidir exactamente con lo que find imprimiría si fuera a imprimir el directorio.parece funcionar igual que
y es más fácil de recordar IMO.
fuente
TLDR: comprenda sus directorios raíz y adapte su búsqueda desde allí, utilizando la
-path <excluded_path> -prune -o
opción No incluya un final/
al final de la ruta excluida.Ejemplo:
find / -path /mnt -prune -o -name "*libname-server-2.a*" -print
Para utilizar de manera efectiva
find
, creo que es imperativo tener una buena comprensión de la estructura de directorios de su sistema de archivos. En la computadora de mi casa tengo discos duros de TB múltiple, con aproximadamente la mitad de ese contenido respaldado usandorsnapshot
(es decir,rsync
). Aunque se realiza una copia de seguridad en una unidad físicamente independiente (duplicada), está montada en el/
directorio raíz ( ) de mi sistema/mnt/Backups/rsnapshot_backups/
:El
/mnt/Backups/rsnapshot_backups/
directorio actualmente ocupa ~ 2.9 TB, con ~ 60 millones de archivos y carpetas; simplemente atravesar esos contenidos lleva tiempo:Por lo tanto, cada vez que necesito buscar un archivo en mi
/
partición (raíz), necesito tratar (evitar si es posible) atravesar mi partición de copias de seguridad.EJEMPLOS
Entre los abordados sugeridos de diversas maneras en este hilo ( Cómo excluir un directorio en el comando find. ), Encuentro que las búsquedas que usan la respuesta aceptada son mucho más rápidas, con advertencias.
Solución 1
Digamos que quiero encontrar el archivo del sistema
libname-server-2.a
, pero no quiero buscar entre misrsnapshot
copias de seguridad. Para encontrar rápidamente un archivo del sistema, use la ruta de exclusión/mnt
(es decir, use/mnt
, not/mnt/
, or/mnt/Backups
, or ...):... encuentra ese archivo en solo unos segundos, mientras que esto toma mucho más tiempo (parece repetirse a través de todos los directorios "excluidos"):
Solución 2
La otra solución ofrecida en este hilo ( SO # 4210042 ) también funciona mal:
RESUMEN | CONCLUSIONES
Utilice el enfoque ilustrado en la " Solución 1 "
es decir
teniendo en cuenta que cada vez que agrega el final
/
a la ruta excluida, elfind
comando ingresa recursivamente (todos esos)/mnt/*
directorios, lo que en mi caso, debido a los/mnt/Backups/rsnapshot_backups/*
subdirectorios, ¡también incluye ~ 2.9 TB de archivos para buscar! Al no agregar un final,/
la búsqueda debe completarse casi de inmediato (en segundos).Del mismo modo, la "Solución 2" (
... -not -path <exclude path> ...
) parece buscar recursivamente a través de los directorios excluidos, no devuelve coincidencias excluidas, pero consume innecesariamente ese tiempo de búsqueda.Buscando dentro de esos
rsnapshot
copias de seguridad:Para encontrar un archivo en una de mis
rsnapshot
copias de seguridad por hora / día / semana / mes ):Excluyendo un directorio anidado:
Aquí, quiero excluir un directorio anidado, por ejemplo,
/mnt/Vancouver/projects/ie/claws/data/*
al buscar desde/mnt/Vancouver/projects/
:Aparte: Agregar
-print
al final del comando suprime la impresión del directorio excluido:fuente
find
, es el número de entradas de directorio que debe examinar. Por lo tanto, es mucho peor si tiene muchos, muchos archivos pequeños (¡especialmente si están todos vinculados de forma múltiple!) Que si solo tiene un puñado de archivos de varios gigabytes.sudo ls -R / | wc -l
indica ~ 76.5M de archivos (la mayoría de los cuales están respaldados excepto los archivos de sistema "no configurados");/mnt/Vancouver/
conls -R | wc -l
indica ~ 2.35M de archivos;/home/victoria/
contiene 0.668M de archivos.También puede usar expresiones regulares para incluir / excluir algunos archivos / directorios de su búsqueda usando algo como esto:
Esto solo le dará todos los archivos js, vue, css, etc. pero excluyendo todos los archivos en las carpetas
node_modules
yvendor
.fuente
Estaba usando
find
para proporcionar una lista de archivosxgettext
y quería omitir un directorio específico y sus contenidos. Intenté muchas permutaciones-path
combinadas con,-prune
pero no pude excluir completamente el directorio que quería que desapareciera.Aunque pude ignorar el contenido del directorio que quería ignorar,
find
luego devolví el directorio como uno de los resultados, lo que provocóxgettext
un bloqueo como resultado (no acepta directorios; solo archivos).Mi solución fue simplemente usar
grep -v
para omitir el directorio que no quería en los resultados:Si hay o no un argumento para
find
que funcione al 100%, no puedo decirlo con certeza. Usargrep
era una solución rápida y fácil después de un dolor de cabeza.fuente
Ninguna de las respuestas anteriores es buena en Ubuntu. Prueba esto:
He encontrado esto aqui
fuente
Esto es adecuado para mí en una Mac:
Excluirá
vendor
y dirigirá elapp/cache
nombre de búsqueda con sufijophp
.fuente
Para aquellos de ustedes en las versiones anteriores de UNIX que no pueden utilizar -path o -no
Probado en SunOS 5.10 bash 3.2 y SunOS 5.11 bash 4.4
fuente
cómo-usar-podar-opción-de-encontrar-en-sh es una excelente respuesta de Laurence Gonsalves sobre cómo
-prune
funciona.Y aquí está la solución genérica:
Para evitar escribir
/path/to/seach/
varias veces, envuélvalafind
en unpushd .. popd
par.fuente
-path
debe coincidir con el nombre que find se imprimiría si se imprimiera el directorio, por ejemplofind . -path ./.git -prune -o -print
, ofind $HOME/foo -path $HOME/foo/.git -prune -o -print
algunas de las respuestas solo dicen-path somedir
cuál es desafortunadamente No es lo suficientemente exacto para ser útil.Por lo que necesitaba, funcionó así, encontrando
landscape.jpg
en todos los servidores comenzando desde la raíz y excluyendo la búsqueda en el/var
directorio:find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg
find / -maxdepth 1 -type d
enumera todos los d irectories en/
grep -v /var
excluye `/ var 'de la listaxargs -I '{}' find '{}' -name landscape.jpg
ejecutar cualquier comando, comofind
con cada directorio / resultado de la listafuente
/
no está excluido todavía. Usted puede necesitarsed 1d
.Los siguientes comandos funcionan:
Si tiene un problema con find, use la
-D tree
opción para ver la información del análisis de expresión.O el
-D all
, para ver toda la información de ejecución.fuente
Encontré el nombre de las funciones en los archivos de fuentes de C excluir * .o y excluir * .swp y excluir (no un archivo normal) y excluir la salida del directorio con este comando:
fuente
Mejor usar la
exec
acción que elfor
bucle:Se
exec ... '{}' ... '{}' \;
ejecutará una vez por cada archivo coincidente, reemplazando las llaves'{}'
con el nombre del archivo actual.Tenga en cuenta que los corchetes están entre comillas simples para protegerlos de la interpretación como puntuación de script de shell * .
Notas
* Desde la sección de EJEMPLOS de la
find (GNU findutils) 4.4.2
página del manualfuente
exec
acción a menudo y me resulta muy útil. Normalmente agrego comillas entre{}
si hay espacios en las rutas de archivo que da"{}"
.{}
funciona para archivos con espacios en blanco en sus nombres) y una mirada a las páginas del manual, parece que las citas solo son necesarias para evitar que se malinterpreten como puntuación de script de shell. En este caso, usaría una cita simple:'{}'
cp
omv
orm
. Lo comprobaréIntenté el comando anterior, pero ninguno de los que usan "-prune" funciona para mí. Finalmente probé esto con el siguiente comando:
fuente