¿Cómo usar la opción ‘-ruta’ de ‘buscar’ en sh?

No entiendo muy bien el ejemplo dado por el ‘hombre encontrado’, ¿alguien puede darme algunos ejemplos y explicaciones? ¿Puedo combinar expresiones regulares en él?


la pregunta más detallada es la siguiente: escriba un script de shell, changeall, que tiene una interfaz como “changeall [-r | -R]” string1 “” string2 “. Encontrará todos los archivos con un sufijo de .h, .C , .cc, o .cpp y cambie todas las ocurrencias de “cadena1” a “cadena2”. -r es la opción para permanecer en el directorio actual solamente o incluyendo el subdirectorio. NOTA: 1) para el caso no recursivo, ‘ls’ NO está permitido , solo pudimos usar ‘find’ y ‘sed’. 2) Intenté ‘find -depth’ pero NO fue compatible. Por eso me preguntaba si ‘-prune’ podría ayudar, pero no entendí el ejemplo de ‘ hombre encuentra ‘.


EDIT2: Estaba haciendo una tarea, no hice una pregunta en gran detalle porque me gustaría terminarla yo mismo. Como ya lo hice y se lo entregué, ahora puedo formular toda la pregunta. Además, logré terminar la tarea sin usar -prune, pero me gustaría aprender de todos modos.

Lo que encuentro confuso acerca de -prune es que es una acción (como -print ), no una prueba (como -name ). Altera la lista de “tareas pendientes”, pero siempre devuelve verdadero .

El patrón general para usar -prune es este:

 find [path] [conditions to prune] -prune -o \ [your usual conditions] [actions to perform] 

-prune siempre quieres el -o inmediatamente después de -prune , porque esa primera parte de la prueba (hasta incluir -prune ) devolverá falso para las cosas que realmente quieres (es decir: las cosas que no quieres eliminar) )

Aquí hay un ejemplo:

 find . -name .snapshot -prune -o -name '*.foo' -print 

Esto encontrará los archivos “* .foo” que no están en los directorios “.snapshot”. En este ejemplo, -name .snapshot es la “prueba de las cosas que quiere podar”, y -name '*.foo' -print es el “material que normalmente pondría después de la ruta”.

Notas importantes :

  1. Si todo lo que quiere hacer es imprimir los resultados, puede que esté acostumbrado a omitir la acción de impresión. Por lo general , no desea hacer eso cuando usa -prune .

    El comportamiento predeterminado de find es “y” la expresión completa con la acción -print si no hay acciones que no sean -prune (irónicamente) al final. Eso significa que escribir esto:

     find . -name .snapshot -prune -o -name '*.foo' # DON'T DO THIS 

    es equivalente a escribir esto:

     find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS 

    lo que significa que también imprimirá el nombre del directorio que está podando, que generalmente no es lo que quiere. En cambio, es mejor especificar explícitamente la acción de -print si eso es lo que desea:

     find . -name .snapshot -prune -o -name '*.foo' -print # DO THIS 
  2. Si su “condición habitual” coincide con archivos que también coinciden con su condición de poda, esos archivos no se incluirán en la salida. La forma de arreglar esto es agregar un predicado -type d a su condición de poda.

    Por ejemplo, supongamos que quisiéramos eliminar cualquier directorio que haya comenzado con .git (esto es algo inventado, normalmente solo debe eliminar algo llamado exactamente .git ), pero aparte de eso quería ver todos los archivos, incluidos los archivos como .gitignore . Puede intentar esto:

     find . -name '.git*' -prune -o -type f -print # DON'T DO THIS 

    Esto no incluiría .gitignore en la salida. Aquí está la versión fija:

     find . -type d -name '.git*' -prune -o -type f -print # DO THIS 

Sugerencia adicional: si está utilizando la versión de GNU de find , la página de texinfo para find tiene una explicación más detallada que su página de manual (como es cierto para la mayoría de las utilidades de GNU).

Tenga en cuenta que -prune no impide descender a ningún directorio como algunos han dicho. Impide descender a directorios que coincidan con la prueba a la que se aplica. Tal vez algunos ejemplos lo ayuden (vea la parte inferior para ver un ejemplo de expresiones regulares). Perdón por ser tan largo.

 $ find . -printf "%y %p\n" # print the file type the first time FYI d . f ./test d ./dir1 d ./dir1/test f ./dir1/test/file f ./dir1/test/test d ./dir1/scripts f ./dir1/scripts/myscript.pl f ./dir1/scripts/myscript.sh f ./dir1/scripts/myscript.py d ./dir2 d ./dir2/test f ./dir2/test/file f ./dir2/test/myscript.pl f ./dir2/test/myscript.sh $ find . -name test ./test ./dir1/test ./dir1/test/test ./dir2/test $ find . -prune . $ find . -name test -prune ./test ./dir1/test ./dir2/test $ find . -name test -prune -o -print . ./dir1 ./dir1/scripts ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.sh ./dir1/scripts/myscript.py ./dir2 $ find . -regex ".*/my.*p.$" ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.py ./dir2/test/myscript.pl $ find . -name test -prune -regex ".*/my.*p.$" (no results) $ find . -name test -prune -o -regex ".*/my.*p.$" ./test ./dir1/test ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.py ./dir2/test $ find . -regex ".*/my.*p.$" -a -not -regex ".*test.*" ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.py $ find . -not -regex ".*test.*" . ./dir1 ./dir1/scripts ./dir1/scripts/myscript.pl ./dir1/scripts/myscript.sh ./dir1/scripts/myscript.py ./dir2 

Normalmente, la forma nativa en que hacemos las cosas en Linux y la forma en que pensamos es de izquierda a derecha.
Así que irás y escribirás lo que estás buscando primero:

 find / -name "*.php" 

Entonces, probablemente presiones enter y te des cuenta de que estás obteniendo demasiados archivos de los directorios que no deseas. Vamos a excluir / medios para evitar buscar en las unidades montadas.
Ahora debería APENDER lo siguiente al comando anterior:

 -print -o -path '/media' -prune 

entonces el comando final es:

 find / -name "*.php" -print -o -path '/media' -prune 

…………… | <--- Incluir ---> | ……………….. | <- -------- Excluir ---------> |

Creo que esta estructura es mucho más fácil y se correlaciona con el enfoque correcto

Agregando al consejo dado en otras respuestas (no tengo representante para crear respuestas) …

Cuando se combina- -prune con otras expresiones, hay una diferencia sutil en el comportamiento dependiendo de qué otras expresiones se usan.

El ejemplo de @Laurence Gonsalves encontrará los archivos “* .foo” que no están en los directorios “.snapshot”: –

 find . -name .snapshot -prune -o -name '*.foo' -print 

Sin embargo, esta mano corta ligeramente diferente incluirá, tal vez inadvertidamente, el directorio .snapshot (y cualquier directorio .snapshot nested): –

 find . -name .snapshot -prune -o -name '*.foo' 

La razón es (de acuerdo con la página de manual en mi sistema):

Si la expresión dada no contiene ninguno de los primarios -exec, -ls, -ok o -print, la expresión dada se reemplaza efectivamente por:

(given_expression) -print

Es decir, el segundo ejemplo es el equivalente a ingresar lo siguiente, modificando así la agrupación de términos:

 find . \( -name .snapshot -prune -o -name '*.foo' \) -print 

Esto se ha visto al menos en Solaris 5.10. Habiendo usado varios sabores de * nix por aproximadamente 10 años, solo recientemente he buscado una razón por la que esto ocurre.

Prune es un no recurse en cualquier cambio de directorio.

Desde la página de manual

Si -depth no se da, verdadero; si el archivo es un directorio, no descienda a él. Si -depth es dado, falso; sin efecto.

Básicamente no desendrá en ningún subdirectorio.

Toma este ejemplo:

Tienes los siguientes directorios

  • / home / test2
  • / home / test2 / test2

Si ejecuta find -name test2 :

Devolverá ambos directorios

Si ejecuta find -name test2 -prune :

Devolverá únicamente / home / test2 ya que no descenderá a / home / test2 para encontrar / home / test2 / test2

No soy un experto en esto (y esta página fue muy útil junto con http://mywiki.wooledge.org/UsingFind )

Recién notado -path es para una ruta que coincide completamente con la cadena / ruta que viene justo después de find (en los ejemplos de tesis) donde as -name coincide con todos los basenames.

 find . -path ./.git -prune -o -name file -print 

bloquea el directorio .git en su directorio actual ( como su hallazgo en )

 find . -name .git -prune -o -name file -print 

bloquea todos los subdirectorios .git recursivamente.

Tenga en cuenta que ./ es extremadamente importante. -path debe coincidir con un camino anclado a . o lo que venga justo después de encontrar si tienes coincidencias sin él (desde el otro lado del o ‘ -o ‘) ¡probablemente no haya sido podado! Estaba ingenuamente inconsciente de esto y me puse de usar -path cuando es genial cuando no quieres podar todos los subdirectorios con el mismo nombre base: D

Muestra todo, incluido el propio directorio, pero no sus contenidos largos y aburridos:

 find . -print -name dir -prune 

Si lees todas las buenas respuestas aquí, mi comprensión ahora es que todas las siguientes devuelven los mismos resultados:

 find . -path ./dir1\* -prune -o -print find . -path ./dir1 -prune -o -print find . -path ./dir1\* -o -print #look no prune at all! 

Pero el último tardará mucho más, ya que todavía busca todo en dir1. Creo que la verdadera pregunta es cómo … -or eliminar los resultados no deseados sin realmente buscarlos.

Así que supongo que podar significa no hacer coincidencias pasadas decentes, sino marcarlo como hecho …

http://www.gnu.org/software/findutils/manual/html_mono/find.html “Sin embargo, esto no se debe al efecto de la acción ‘-ruta’ (que solo previene el descenso adicional, no se asegura ignoramos ese elemento). En cambio, este efecto se debe al uso de ‘-o’. Dado que el lado izquierdo de la condición “o” ha tenido éxito para ./src/emacs, no es necesario evaluar el derecho lado de la mano (‘-print’) para este archivo en particular “.

    Intereting Posts