Pregunta

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


La pregunta más detallada es así:

Escribe 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 cambiar todas las apariciones de string1 a string2. -r Es una opción para permanecer solo en el directorio actual o incluir subdirectorios.

NOTA:

  1. Para el caso no recursivo, ls NO está permitido, solo podríamos usar find y sed.
  2. Lo intenté find -depth pero NO fue compatible.Por eso me preguntaba si -prune podría ayudar, pero no entendí el ejemplo de man find.

EDITAR2:Estaba haciendo una tarea, no hice preguntas detalladas porque me gustaría terminarla yo mismo.Como ya lo hice y lo entregué, ahora puedo plantear la pregunta completa.Además, logré terminar la tarea sin usar -prune, pero me gustaría aprenderlo de todos modos.

¿Fue útil?

Solución

De lo que había encontrado confuso -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 esto:

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

Casi siempre quieres el -o (lógico o) inmediatamente después -prune, porque esa primera parte de la prueba (hasta e incluyendo -prune) regresará falso por las cosas que realmente quieres (es decir: las cosas que no quiero podar).

Aquí hay un ejemplo:

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

Esto encontrará los archivos "*.foo" que no están debajo ".snapshot" Directorios. En este ejemplo, -name .snapshot constituye el [conditions to prune], y -name '*.foo' -print es [your usual conditions] y [actions to perform].

Notas importantes:

  1. Si todo lo que desea hacer es imprimir los resultados que puede estar utilizado para dejar de lado el -print acción. Usted generalmente no quiero hacer eso cuando use -prune.

    El comportamiento predeterminado de Find es "y" el completo expresión con el -print acción si no hay más acciones que -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 desea. En su lugar, es mejor especificar explícitamente el -print Acción si eso es lo que quieres:

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

    Por ejemplo, supongamos que queríamos podar cualquier directorio que comenzara con .git (Esto es cierto que es algo artificial; normalmente solo necesita eliminar la cosa llamada exactamente .git), pero aparte de eso quería ver todos los archivos, incluidos archivos como .gitignore. Podrías probar esto:

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

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

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

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

Otros consejos

Tenga cuidado de que -PRUNE no evite descender a ningún Directorio como algunos han dicho. Evita descender a directorios que coinciden con la prueba a la que se aplica. Quizás algunos ejemplos ayuden (vea la parte inferior para un ejemplo de regex). Perdón por que esto sea 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 en que hacemos las cosas en Linux y la forma en que creemos que es de izquierda a derecha.
Entonces irías a escribir lo que estás buscando primero:

find / -name "*.php"

Entonces probablemente presione Enter y se dé cuenta de que está obteniendo demasiados archivos de los directorios que desea no. Excluyamos /medios para evitar buscar en sus unidades montadas.
Ahora debería agregar lo siguiente al comando anterior:

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

Entonces el comando final es:

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

............... | <--- Incluya ---> | .................... | <- -------- excluir ---------> |

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

Además del consejo dado en otras respuestas (no tengo representantes para crear respuestas) ...

Al combinar -prune Con otras expresiones, hay una diferencia sutil en el comportamiento dependiendo de qué otras expresiones se usen.

El ejemplo de @Laurence Gonsalves encontrará los archivos "*.foo" que no están en ".snapshot" Directorios:-

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

Sin embargo, esta mano corta ligeramente diferente, tal vez inadvertidamente, también enumerará el .snapshot Directorio (y cualquier directorios .snapshot anidados):-

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

La razón es (según la mano de obra en mi sistema):-

Si la expresión dada no contiene ninguna de las primarias -exec, -ls, -ok o -impresión, la expresión dada se reemplaza efectivamente por:

(ded_expression) -impresión

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 al menos se ha visto en Solaris 5.10. Después de haber usado varios sabores de *nix durante aproximadamente 10 años, recientemente busqué una razón por la cual esto ocurre.

Prune es un no recurrir en ningún interruptor de directorio.

De la página del hombre

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

Básicamente, no se desviará en ningún subtirectorio.

Tome este ejemplo:

Tienes los siguientes directorios

  • /Inicio/Test2
  • /Home/Test2/Test2

Si tu corres find -name test2:

Devolverá ambos directorios

Si tu corres find -name test2 -prune:

Volverá solamente/home/test2, ya que no descendería 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)

Me acabo de dar cuenta -path es para un camino que coincide completamente con la cadena/ruta que viene justo después find (. en estos ejemplos) donde como como -name coincide con todos los nombres de base.

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

bloquea el directorio .git en su directorio actual ( Como tu hallazgo en . )

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

Bloquea todos los subdirectorios .git recursivamente.

Nota la ./ es extremadamente importante !! -path debe coincidir con una ruta anclada con . o lo que viene justo después de encontrar Si obtienes partidos sinlo (desde el otro lado del o '-o') ¡Probablemente no haya podado! No era ingenuo de esto y me puso a usar el camino cuando es genial cuando no quieres podar todo el subdirectorio con el mismo nombre de base: D

Muestre todo, incluido el Dir en sí, pero no sus contenidos largos y aburridos:

find . -print -name dir -prune

Si lees todas las buenas respuestas aquí, ahora entiendo que las siguientes arrojan 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 llevará mucho más tiempo ya que todavía busca todo en el directorio 1.Supongo que la verdadera pregunta es cómo -or resultados no deseados sin tener que buscarlos.

Así que supongo que podar significa no decentes los partidos pasados, sino marcarlos como hechos...

http://www.gnu.org/software/findutils/manual/html_mono/find.html"Sin embargo, esto no se debe al efecto de la acción '-poda' (que sólo evita un mayor descenso, no garantiza que ignoremos ese elemento).En cambio, este efecto se debe al uso de '-o'.Dado que el lado izquierdo de la condición "o" se realizó correctamente para ./src/emacs, no es necesario evaluar el lado derecho ("-print") para este archivo en particular".

find Construye una lista de archivos. Aplica el predicado que suministró a cada uno y devuelve los que pasan.

Esta idea que -prune Significa excluir de los resultados fue realmente confuso para mí. Puede excluir un archivo sin podar:

find -name 'bad_guy' -o -name 'good_guy' -print  // good_guy

Todos -prune lo hace es alterar el comportamiento de la búsqueda. Si la coincidencia actual es un directorio, dice "Oye find, ese archivo que acaba de igualar, no desciendan a él ". Simplemente elimina ese árbol (pero no el archivo en sí) de la lista de archivos para buscar.

Debería ser nombrado -dont-descend.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top