Come eseguo più comandi quando utilizzo find?


57

Sto cercando di eseguire più comandi su cose che ho trovato, come posso ottenere questo?

find . -exec cmd1; cmd2

non sembra funzionare; invece esegue cmd2 dopo che cmd1 è stato eseguito su ogni file.

Risposte:


40

In questa dimostrazione, userò sh -c 'echo first; false'(o true) per il primo -exec. Ciò fornirà un output e avrà anche l'effetto del codice di uscita selezionato. Quindi echo secondverrà utilizzato per il secondo. Supponiamo che ci sia un file nella directory corrente.

$ find . -type f -exec sh -c 'echo first; false' \; -exec echo second \;
first
$ find . -type f -exec sh -c 'echo first; true' \; -exec echo second \;
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second

Un vero comando di questo tipo sarebbe simile a:

find . -type f \( -exec command1 \; -false -o -exec command2 \; \)

Nel secondo set, le parentesi di escape raggruppano le due -execclausole. Il rapporto -falsetra loro forza lo stato del test su "false" e -ocausa la -execvalutazione dell'espressione successiva (la seconda ) a causa di -false.

Da man find:

expr1 expr2
Vengono prese due espressioni di seguito da unire con un "e" implicito; expr2 non viene valutato se expr1 è falso.

expr1 -a expr2
Come per expr1 expr2.

expr1 -o expr2
Oppure; expr2 non viene valutato se expr1 è true.


Ah sì, me ne sono dimenticato -o.
Ignacio Vazquez-Abrams,

32

Se non ti interessa che cmd1 sia in grado di impedire l'esecuzione di cmd2 a causa del codice di errore 0:

find . -exec cmd1 \; -exec cmd2 \;

L'unico modo affidabile per far eseguire sempre entrambi i comandi è quello di avere findinvocato una shell che eseguirà successivamente i comandi in sequenza:

find . -exec bash -c 'cmd1; cmd2' filedumper {} \;

2

Se non ti dispiace creare uno script che esegua cmd1 e cmd2, allora è proprio questo:

find . -exec myscript {} \;

o

find . -exec myscript {} +

Uso \; o + a seconda che myscript sia in grado di gestire più di un file alla volta (diventa peloso se ci sono spazi nei nomi dei file, ecc.).

Inserire ciò che stavi facendo in una sceneggiatura, nella mia esperienza, è quasi sempre valsa la pena. Se devi farlo una volta, dovrai farlo di nuovo.

Ma un trucco accurato è quello di mettere la scoperta all'interno della sceneggiatura:

if [ $# -gt 0 ]; then
    for each; do
        touch $each
    done
else
    find . -exec $0 {} +
fi

Quindi myscript funziona su tutti i file che fornisci come argomenti su cui lavorare, ma se non gli dai alcun argomento, esegue find dalla directory corrente e quindi si chiama sui file trovati. Ciò aggira il fatto che find -exec non può chiamare le funzioni shell definite nello script.


0

Ho provato entrambe le soluzioni precedenti senza molta fortuna. Questo ha funzionato bene per me:

$ for i in `find . -exec echo {} \;`; do cmd1 $i; cmd2 $i; done

Questo non funzionerà se l'elenco dei file è troppo grande.
Alex,

-3

prova il comando:

sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l

4
Eh, non è una buona idea. Il *nella -execparte si espanderà a tutti i file nella directory corrente. Soprattutto quando si esegue come sudo.
slhck,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.