¿Cómo evito que un hallazgo descienda a los directorios encontrados?

24

Quiero encontrar todos los directorios con una cadena específica para poder hacer otra búsqueda en los archivos que contiene.

Así que no quiero perder el tiempo en ./my-search-term/dir/my-search-termetc.

¿Cómo puedo dejar de recurrir cuando encuentro el primer directorio my-search-term?

Stephen
fuente
3
¿Has intentado encontrar con -prune? Desde la página de manual: "si el archivo es un directorio, no descienda a él. Si se proporciona -depth, falso; sin efecto. Debido a que -delete implica -depth, no puede usar -prune y -delete juntos".
laebshade
1
@laebshade ¿por qué no pones eso en una respuesta?
jw013
@ jw013 No tuve tiempo de dar una respuesta más profunda en ese momento.
laebshade

Respuestas:

17

La -pruneacción hace que findno se repita en el directorio. Puede combinarlo con otra acción como -exec(el orden de -pruney -execno importa, siempre que -prunese ejecute de cualquier manera).

find . -name my-search-term -prune -exec find {} … \;

Tenga en cuenta que anidar finddentro de a find -execpuede ser un poco problemático: no se puede usar -execen el interior find, porque el terminador sería visto como un terminador por el exterior find. Puede evitar eso invocando un shell, pero tenga cuidado con las citas.

find . -name my-search-term -prune -exec sh -c '
    find "$@" … -exec … {\} +
' _ {} +
Gilles 'SO- deja de ser malvado'
fuente
¿Son necesarios los paréntesis en su primer comando? -prunedevuelve verdadero y se puede poner antes de -exec.
rozcietrzewiacz
@rozcietrzewiacz No, no son necesarios. Hábito de tener -oallí, supongo. Y supongo que poner -pruneantes -execes más legible.
Gilles 'SO- deja de ser malvado'
Gracias, no usé la -pruneopción antes.
haridsv
En mi caso de uso, este comando: mkdir -p x1 x2; touch x1/x11 x1/x12 x2/x21 x2/x22; find . -name 'x1*' -exec rm -rf {} \;da el error: find: ./x1: No such file or directory. La solución es agregar -pruneal final del findcomando.
haridsv
(1) Algunas versiones de findexpandir {}incluso cuando aparece como una subcadena de un argumento para -exec. Tal versión de findse ahogará en su segundo comando, porque el comando {}interno find(en el comando de shell) será reemplazado por el nombre del directorio que se encuentra en el externo find. Puede arreglar eso diciendo find . -name my-search-term -prune -exec sh -c 'find "$0" … -exec … "{"} +' {} \; , es decir, usando "{"}, en lo que se convertirá el shell {}. ... (Continúa)
Scott
6

- soluciones desnudas -

Si desea findomitir los contenidos del directorio encontrado, pero continúa buscando en otros directorios, use -prunecomo sugirió @laebshade. El comando completo debería verse así

 find . -type d -name somename -prune -exec ...

Por otro lado, si desea dejar de buscarfind por completo y después de encontrar el primer directorio coincidente, entonces lo que está buscando es (disponible desde la versión de ). Este es un poco más complicado de usar, ya que hace que la salida sea inmediata, por lo que debe colocarse al final del comando:-quit4.2.3GNU findfind-quit

find . -type d -name somename -exec ... -quit

Para que esto funcione como se esperaba, uno tiene que asegurarse de que los -execretornos sean verdaderos (en otras palabras, un estado cero ). Si desea -execque se ignore el estado de salida de , para que eso -quitsiempre funcione, necesita un pequeño truco:

find . -type d -name somename \( -exec ... -o -true \) -quit

o

find . -type d -name somename \( -exec ... -o -quit \)

o

find . -type d -name somename \( -exec ... , -quit \) # a comma before -quit

- alguna explicación -

Lo más importante acerca de cómo findfunciona es que todas las acciones ("pruebas") se tratan como predicados lógicos interpretados de izquierda a derecha. Por lo tanto, la última acción (por ejemplo -quit) solo se realizará si toda la parte anterior no devolvió falso . Por defecto, todas las pruebas se unen con "AND" lógico, la -oopción cambia la unión a "OR".

Un elemento complicado -oes que findpuede "optimizar" su comando y no ejecutar la -execparte si escribe solo

find . -type d -name somename -exec ... -o -quit

Para hacer frente a eso, puede forzar finda evaluar todos los predicados con "O", encerrándolos entre paréntesis.

rozcietrzewiacz
fuente