Domanda

Non capisco del tutto l'esempio fornito da man find, qualcuno può darmi qualche esempio e spiegazione?Posso combinare l'espressione regolare in esso?


La domanda più dettagliata è questa:

Scrivi uno script di shell, changeall, che ha un'interfaccia simile changeall [-r|-R] "string1" "string2".Troverà tutti i file con il suffisso .h, .C, .cc, O .cpp e modificare tutte le occorrenze di string1 A string2. -r è un'opzione per rimanere solo nella directory corrente o includere le sottodir.

NOTA:

  1. Per il caso non ricorsivo, ls NON è consentito, potremmo solo usare find E sed.
  2. ho provato find -depth ma NON era supportato.Ecco perché mi chiedevo se -prune potrebbe aiutare, ma non ho capito l'esempio man find.

EDIT2:Stavo svolgendo un compito, non ho posto domande nei dettagli perché vorrei finirlo da solo.Dato che l'ho già fatto e consegnato, ora posso formulare l'intera domanda.Inoltre, sono riuscito a completare il compito senza utilizzarlo -prune, ma vorrei impararlo comunque.

È stato utile?

Soluzione

La cosa su cui avevo trovato confuso -prune è che è un'azione (come -print), non un test (come -name).Altera l'elenco delle "cose ​​da fare", ma restituisce sempre vero.

Il modello generale per l'utilizzo -prune è questo:

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

Praticamente lo vuoi sempre -o (OR logico) immediatamente dopo -prune, perché quella prima parte del test (fino a incluso -prune) sarà di ritorno falso per le cose che realmente desideri (ad esempio:le cose che tu non voglio eliminare).

Ecco un esempio:

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

Questo troverà i file "*.foo" che non si trovano nelle directory ".snapshot".In questo esempio, -name .snapshot costituisce il [conditions to prune], E -name '*.foo' -print È [your usual conditions] E [actions to perform].

Note importanti:

  1. Se tutto ciò che vuoi fare è stampare i risultati potresti essere abituato a tralasciare il file -print azione.Tu in genere non vuoi farlo quando lo usi -prune.

    Il comportamento predefinito di find è "e" the intero espressione con il -print azione se non ci sono azioni diverse da -prune (ironicamente) alla fine.Ciò significa che scrivendo questo:

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

    equivale a scrivere questo:

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

    il che significa che stamperà anche il nome della directory che stai eliminando, che di solito non è quello che desideri.E' invece meglio specificare esplicitamente il -print azione se è quello che vuoi:

    find . -name .snapshot -prune -o -name '*.foo' -print       # DO THIS
    
  2. Se la tua "condizione abituale" corrisponde a file che corrispondono anche alla tua condizione di prune, quei file lo faranno non essere incluso nell'output.Il modo per risolvere questo problema è aggiungere a -type d dipendente dalle condizioni della tua prugna.

    Ad esempio, supponiamo di voler eliminare qualsiasi directory che inizia con .git (questo è certamente un po' artificioso: normalmente è sufficiente rimuovere solo la cosa denominata esattamente .git), ma a parte questo volevo vedere tutti i file, inclusi i file come .gitignore.Potresti provare questo:

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

    Questo sarebbe non includere .gitignore nell'uscita.Ecco la versione fissa:

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

Suggerimento extra:se stai utilizzando la versione GNU di find, la pagina texinfo per find ha una spiegazione più dettagliata della sua manpage (come è vero per la maggior parte delle utility GNU).

Altri suggerimenti

Attenzione che -prune non impedisce scendere in qualsiasi directory come alcuni hanno detto. Previene scendendo nelle directory che corrispondono il test è applicato a. Forse alcuni esempi aiuteranno (vedere il fondo per un esempio di espressione regolare). Ci scusiamo per questo essere così lungo.

$ 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 il modo nativo che fare le cose in Linux e il nostro modo di pensare è da sinistra a destra.
Quindi, si dovrebbe andare e scrivere quello che stai cercando per il primo:

find / -name "*.php"

allora probabilmente ha colpito entrare e rendersi conto che si stanno ottenendo troppi file da directory non si desidera. Diamo escludere / media per evitare la ricerca le unità montate.
Si dovrebbe ora solo aggiungere il seguente al comando precedente:

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

in modo che il comando finale è:

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

............... | <--- Includere ---> | .................... | <---------- --------- escludere> |

Credo che questa struttura è molto più facile e correlato al giusto approccio

In aggiunta al consiglio dato in altre risposte (non ho rep per creare risposte) ...

Quando si combina -prune con altre espressioni, c'è una sottile differenza nel comportamento a seconda di quale altre espressioni vengono utilizzati.

Esempio

@Laurence Gonsalves' si trova il "* .foo" i file che non sono sotto ".snapshot" directory: -

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

Tuttavia, questo leggermente diverso a breve mano sarà, forse inavvertitamente, elencare anche la directory .snapshot (e le directory .snapshot nidificate): -

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

Il motivo è (secondo la pagina di manuale sul mio sistema): -

  

Se l'espressione data non contiene alcuna delle primarie -exec,   -ls, -ok o -print, l'espressione data è efficacemente sostituito da:

     

(given_expression) -print

Cioè, il secondo esempio è l'equivalente di entrare nel seguito, così da modificare il raggruppamento dei termini: -

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

Questa è almeno stato visto su Solaris 5.10. Avendo usato vari sapori di * nix per circa 10 anni, ho solo recentemente cercato un motivo per cui questo accade.

Prune è un non FattorialeMenoUno cambiato in ogni directory.

Dalla pagina man

  

Se -depth non è dato, vero;         se il file è una directory, non scende in esso.     Se viene dato -depth, false; nessun effetto.

In sostanza non sarà desend in qualsiasi sottodirectory.

Prendete questo esempio:

Sono disponibili le seguenti directory

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

Se si esegue find -name test2:

Si tornerà entrambe le directory

Se si esegue find -name test2 -prune:

Si tornerà solo / home / test2 in quanto non scenderà in / home / test2 per trovare / home / test2 / test2

Non sono un esperto in questo (e questa pagina è stato molto disponibile con http://mywiki.wooledge.org / UsingFind )

-path

Appena notato è per un percorso che corrisponde pienamente la stringa / percorso che viene subito dopo find (. in tesi esempi) dove, come -name corrisponde a tutti BaseNames.

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

blocca la directory .git nella directory corrente ( come risultato in . )

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

blocca tutte le sottodirectory .git ricorsivamente.

Si noti la ./ è estremamente importante !! -path deve corrispondere a un percorso ancorata al . o ciò che viene subito dopo trovare se si ottiene incontri fuori di esso (dall'altra parte del o '-o') probabilmente non essere potati! Io ero ingenuamente a conoscenza di questo e mi ha messo di utilizzare path quando è grande quando non si vuole potare tutte sottodirectory con lo stesso nome di base: D

Mostra tutto, compreso dir se stesso, ma non i suoi lunghi contenuti noiose:

find . -print -name dir -prune

Se avete letto tutte le buone risposte qui la mia comprensione è che ora il seguente restituiscono tutte lo stesso risultato:

find . -path ./dir1\*  -prune -o -print

find . -path ./dir1  -prune -o -print

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

Ma l'ultimo avrà molto più a lungo in quanto cerca ancora fuori tutto in dir1. Credo che la vera questione è come -or fuori risultati indesiderati senza peraltro riuscire a cercare.

Quindi credo che i mezzi prugna fanno partite passate non decenti ma contrassegnarla come eseguita ...

http://www.gnu.org/software/findutils/ manuale / html_mono / find.html "Questo però non è per effetto dell'azione '-prune' (che impedisce solo ulteriore discesa, non fa che noi ignoriamo che articolo). Invece, questo effetto è dovuto all'uso di '-o'. Dal momento che il lato sinistro della “o” condizione è riuscita per ./src/emacs, non è necessario valutare il diritto-mano-lato ( '-print') a tutti per questo particolare file ".

find crea un elenco di file. Si applica il predicato che hai fornito a ciascuno e restituisce quelli che passano.

Questa idea che -prune mezzi escludere dai risultati era davvero fonte di confusione per me. È possibile escludere un file senza prugna:

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

Tutti -prune fa è modificare il comportamento della ricerca. Se la partita in corso è una directory, si dice "hey find, che file appena abbinato, Non scendere in esso" . Rimuove solo quell'albero (ma non il file stesso) dalla lista dei file per la ricerca.

Si deve essere denominato -dont-descend.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top