Cosa significa "{} \;" nel comando find?


38

A volte vedo il seguente comando:

find . -name  * -exec ls -a {} \;

Mi è stato chiesto di eseguire questo.

Cosa {} \;significa qui?


2
-name *è ridondante.
Kevin,

3
Dai un'occhiata a spiega Shell per altri tipi di domande come questa. Ecco l'output per il tuo comando. .
Glutanimate,

10
-name *è peggio che ridondante. Poiché *non è quotato, la shell lo espande nell'elenco dei nomi dei file nella cartella corrente, con spazi trattati in modo errato, portando a risultati imprevisti o un messaggio di errore. Come punto in più, findha molte funzioni, una delle quali è quella di elencare i file; questo evita di dover usare -exec. Ad esempio, puoi usare find . -printo find . -ls. Infine, ci sono due modi per sfuggire il punto e virgola: o come avete fatto con la barra inversa, \;o citando: ';'. Usa quello con cui ti senti più a tuo agio.
Paddy Landau,

Risposte:


49

Se si esegue findcon exec, {}si espande al nome del file di ogni file o directory trovati con find(in modo che lsnel tuo esempio ottiene ogni riscontrata nome di file come argomento - nota che chiama lso qualunque altro comando si definisce una volta per ogni file trovato).

Il punto e virgola ;termina il comando eseguito da exec. Deve essere evaso in \modo che la shell findall'interno della quale corri non la tratti come il suo carattere speciale, ma piuttosto la passi a find.

Vedere questo articolo per ulteriori dettagli.


Inoltre, findfornisce alcune ottimizzazioni con exec cmd {} +: quando eseguito in questo modo, findaggiunge i file trovati alla fine del comando anziché invocarlo una volta per file (in modo che il comando venga eseguito una sola volta, se possibile).

La differenza nel comportamento (se non in efficienza) è facilmente evidente se eseguita con ls, ad es

find ~ -iname '*.jpg' -exec ls {} \;
# vs
find ~ -iname '*.jpg' -exec ls {} +

Supponendo di avere alcuni jpgfile (con percorsi abbastanza corti ), il risultato è una riga per file nel primo caso e un lscomportamento standard di visualizzazione dei file in colonne per quest'ultimo.


1
Penso che sarebbe vantaggioso per voi a contrasto \;con +.
Kevin,

In cosa differisce da find . -name * | ls -a -?
András Hummer,

@DrH Il punto non è lasciare che shell esegua l'espansione jolly ma piuttosto passare l'espressione jolly a find. Inoltre, l'output di lsin questo caso apparentemente non dipende dall'input - indipendentemente da ciò che uso come filtro find, lsvisualizza solo il contenuto della directory di lavoro e questo è tutto. Verificare ad esempio find ~ -iname '*.jpg' -exec ls -a {} \;vs find ~ -iname '*.jpg' | ls -a.
moon.musick,

@DrH o anche echo 'foo' | ls -a.
moon.musick,

@ moon.musick, credo che ti sia perso l'importante -nel tuo ls -a -comando durante il test di ciò che ha richiesto @ dr-h.
Daniel Llewellyn,

21

Dalla manpage per il findcomandoIcona Manpage :

-exec command ;
              Execute  command;  true if 0 status is returned.  All following arguments to find are taken to be arguments to
              the command until an argument consisting of `;' is encountered.  The string `{}' is replaced  by  the  current
              file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it
              is alone, as in some versions of find.  Both of these constructions might need to be escaped (with a  `\')  or
              quoted  to  protect them from expansion by the shell.

Quindi, ecco la spiegazione:

{}significa "l'output di find". Come in "qualunque cosa findtrovata". findrestituisce il percorso del file che stai cercando, giusto? Quindi lo {}sostituisce; è un segnaposto per ogni file che il findcomando individua (preso da qui ).

La \;parte sostanzialmente dice find"ok, ho finito con il comando che volevo eseguire".

Esempio:

Diciamo che sono in una directory piena di .txtfile. Quindi corro:

find . -name  '*.txt' -exec cat {} \;

La prima parte, find . -name *.txtrestituisce un elenco dei .txtfile. La seconda parte, -exec cat {} \;eseguirà il catcomando per ogni file trovato dai find, così cat file1.txt, cat file2.txte così via.


4
La parte *.txtdeve essere citata come '*.txt'. Questo perché se ci sono .txtfile nella cartella corrente, la shell lo espanderà e otterrai risultati errati o un messaggio di errore. find -name '*.txt' -exec cat {} \;
Paddy Landau,

@Alaa Ali ha spiegato molto bene
pushya
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.