La risposta di Muru è appropriata e adatta per i casi in cui vogliamo stampare qualcosa se viene trovato il file. Per un caso generale quando vogliamo eseguire un comando esterno, come ad esempio echo
, potremmo usare -exec
flag.
$ find . -name 'xac' -exec echo "I found " {} \; -quit
I found ./xac
La {}
parte passa il nome file al comando tra -exec
e \;
come argomenti. Nota \
prima ;
: impedisce alla shell di interpretare erroneamente ; nel punto e virgola di chiusura della shell indica la fine del comando, ma quando viene evasa con una barra, la shell lo tratterà come un testo letterale da passare al find
comando e per trovare il comando serve come -exec
argomento di chiusura della bandiera.
Per costruire condizionali del if found do this; else do that
genere, potremmo usare il comando substition $()
e test
command (aka [
):
$ [ "x$(find . -name 'noexist' -print -quit)" != "x" ] && echo "found" || echo "not found"
not found
$ [ "x$(find . -name 'xac' -print -quit)" != "x" ] && echo "found" || echo "not found"
found
Affrontare il commento di Dan
Dan nei commenti ha chiesto:
L'eco "Ho trovato {}" non sarebbe migliore dell'eco "Ho trovato" {}? Forse per l'eco va bene, ma se qualcuno copia il comando e sostituisce l'eco con un altro comando, potrebbe avere un problema
Capiamo prima il problema. Di solito, nelle shell esiste il concetto di suddivisione delle parole, il che significa che variabili non quotate e parametri posizionali verranno espansi e trattati come elementi separati. Per esempio, se si dispone di variabili var
e contiene hello world
il testo, quando si esegue touch $var
la shell scomposizione in due elementi separati hello
e world
e touch
capirà che come se si stesse cercando di creare 2 file separati; se lo fai touch "$var"
, allora shell tratterà hello world
come una sola unità e touch
creerà un solo file. Questo è importante per capire che ciò accade solo a causa del funzionamento delle shell.
Al contrario, find
non soffre di tale comportamento, poiché i comandi vengono elaborati da find
soli ed eseguiti da una execvp()
chiamata di sistema, quindi non è coinvolta alcuna shell. Mentre le parentesi graffe hanno un significato speciale nelle shell, perché appaiono nel mezzo del find
comando e non all'inizio, in questo caso non hanno alcun significato speciale per le shell. Ecco un esempio Creiamo alcuni nomi di file difficili e proviamo a passarli come argomento da stat
comandare.
$ touch with$'\t'tab.txt with$' 'space.txt with$'\n'newline.txt
$ find -type f -exec stat -c "%F" {} \; -print
regular empty file
./with?newline.txt
regular empty file
./with space.txt
regular empty file
./with?tab.txt
Come puoi vedere, stat
riceve perfettamente nomi di file difficili find
, il che è uno dei motivi principali per cui è raccomandato per l'uso in script portatili e particolarmente utile quando stai attraversando l'albero di directory e vuoi fare qualcosa con nomi di file che potrebbero potenzialmente avere personaggi speciali in loro. Pertanto, non è necessario citare parentesi graffe per i comandi eseguiti in find
.
È una storia diversa quando viene coinvolta la shell. A volte è necessario utilizzare una shell per elaborare il nome file. In tal caso, la quotazione sarà davvero importante, ma è importante rendersi conto che non è un problema di ricerca: è la shell che fa la divisione delle parole.
$ find -type f -exec bash -c "stat {}" sh \;
stat: cannot stat './with': No such file or directory
sh: line 1: newline.txt: command not found
stat: cannot stat './with': No such file or directory
stat: cannot stat 'space.txt': No such file or directory
stat: cannot stat './with': No such file or directory
stat: cannot stat 'tab.txt': No such file or directory
Quindi quando citiamo all'interno della shell , funzionerà. Ma ancora una volta, questo è importante per la shell, no find
.
$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;
regular empty file
regular empty file
regular empty file
/some/path
dice a dove iniziare a cercare, ma nulla gli dice cosa cercare. Lo stesso nella tua risposta collegata. Ciò che funziona per me èfind /some/path -name xac -print0 -quit | grep -qz . && echo found
. Ho dimenticato qualcosa?