Excluir un subdirectorio usando buscar

115

Tengo una estructura de directorio como esta

data
|___
   |
   abc
    |____incoming
   def
    |____incoming
    |____processed
   123
    |___incoming
   456
    |___incoming
    |___processed

Hay una subcarpeta entrante en todas las carpetas dentro del directorio de datos. Quiero obtener todos los archivos de todas las carpetas y subcarpetas excepto los directorios def / entrante y 456 / entrante. Probé con el siguiente comando

 find /home/feeds/data -type d \( -name 'def/incoming' -o -name '456/incoming' -o -name arkona \) -prune -o -name '*.*' -print

pero no funciona como se esperaba.

Ravi

Ravi
fuente
3
Este no es un buen consejo, pero te sacará de muchas situaciones rápido y sucio: canaliza eso grep -v somethingpara excluir lo que sea que no quieras
Miquel
¿Responde esto a tu pregunta? Cómo excluir un directorio en find. comando
imz - Ivan Zakharyaschev

Respuestas:

206

Esto funciona:

find /home/feeds/data -type f -not -path "*def/incoming*" -not -path "*456/incoming*"

Explicación:

  • find /home/feeds/data: comienza a buscar de forma recursiva desde la ruta especificada
  • -type f: buscar archivos solamente
  • -not -path "*def/incoming*": no incluya nada def/incomingcomo parte de su ruta
  • -not -path "*456/incoming*": no incluya nada 456/incomingcomo parte de su ruta
sampson-chen
fuente
obteniendo un error "buscar: opción incorrecta -no encontrar: lista de rutas lista de predicados"
Ravi
@Ravi, ¿estás usando bash shell? Acabo de probar esto en mi terminal y funciona para mí. Intente copiar y pegar la solución en su lugar si realizó modificaciones en su secuencia de comandos.
sampson-chen
Está funcionando, pero está enumerando los directorios, no los archivos en esos directorios.
Ravi
1
-pathcoincide con toda la cadena, por lo que si lo está haciendo find ., entonces sus -pathcadenas deben ser./path/to/directory/*
Heath Borders
1
Para su información, -not -pathdefinitivamente funcionará en este ejemplo, pero findaún está iterando en la estructura de directorios y utilizando ciclos de CPU para iterar sobre todos esos directorios / archivos. para evitar finditerar sobre esos directorios / archivos (tal vez haya millones de archivos allí), entonces debe usar -prune(la -pruneopción es difícil de usar).
Trevor Boyd Smith
9

Solo por el bien de la documentación: es posible que deba profundizar más, ya que hay muchas constelaciones de búsqueda y omisión (como tuve que hacerlo). Puede resultar que prunesea ​​tu amigo mientras -not -pathque no hará lo que esperas.

Así que este es un valioso ejemplo de 15 ejemplos de búsqueda que excluyen directorios:

http://www.theunixschool.com/2012/07/find-command-15-examples-to-exclude.html

Para vincular a la pregunta inicial, la exclusión finalmente funcionó para mí así:

find . -regex-type posix-extended -regex ".*def/incoming.*|.*456/incoming.*" -prune -o -print 

Luego, si desea encontrar un archivo y aún excluir parches, simplemente agregue | grep myFile.txt.

También puede depender de su versión de búsqueda. Veo:

$ find -version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX
peter_the_oak
fuente
5

-namesolo coincide con el nombre del archivo, no con la ruta completa. En su -pathlugar, desea utilizar para las partes en las que está podando los directorios como def/incoming.

Brian Campbell
fuente
2
find $(INP_PATH} -type f -ls |grep -v "${INP_PATH}/.*/"
Vishal Pathak
fuente
7
Algunas explicaciones pueden convertir esto en una respuesta mucho mejor.
Cris Luengo
Gracias por este fragmento de código, que puede proporcionar una ayuda limitada a corto plazo. Una explicación adecuada mejoraría enormemente su valor a largo plazo al mostrar por qué es una buena solución al problema y lo haría más útil para futuros lectores con otras preguntas similares. Edite su respuesta para agregar alguna explicación, incluidas las suposiciones que hizo
Shawn C.
1
Nota: este truco no funciona si se usa find ... -print0junto con un posteriorxargs -0
phs