Odpowiedź muru jest odpowiednia i dobrze nadaje się do przypadków, w których chcemy coś wydrukować, jeśli plik zostanie znaleziony. W ogólnym przypadku, gdy chcemy wykonać polecenie zewnętrzne, np. echo
Możemy użyć -exec
flagi.
$ find . -name 'xac' -exec echo "I found " {} \; -quit
I found ./xac
{}
Część przechodzi pliku do polecenia pomiędzy -exec
i \;
jako argumenty. Zauważ, że \
przed ;
- zapobiega powłoki z misinterpreting go; w muszli zamykania oznacza rednikami końca polecenia, ale gdy uciekł z kreską, powłoka będzie traktować go jako tekst literall być przekazane do find
polecenia i znaleźć polecenie służy jako zamknięcie -exec
argumenty bandery.
Do konstruowania tego if found do this; else do that
rodzaju warunków możemy użyć podstacji polecenia $()
i test
polecenia (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
Zwracając się do komentarza Dana
Dan w komentarzach zapytał:
Czy echo „Znalazłem {}” nie byłoby lepsze niż echo „Znalazłem" {}? Może dla echa jest w porządku, ale jeśli ktoś skopiuje polecenie i zastąpi echo innym poleceniem, może mieć problem
Najpierw zrozummy problem. Zwykle w powłokach występuje koncepcja podziału słów, co oznacza, że niecytowane zmienne i parametry pozycyjne będą rozszerzane i traktowane jako osobne elementy. Na przykład, jeśli masz zmienną var
i zawiera hello world
tekst, gdy zrobisz touch $var
powłoka będzie rozbicie go na dwie odrębne pozycje hello
i world
i touch
zrozumie, że tak, jakbyś próbował utworzyć 2 oddzielne pliki; jeśli to zrobisz touch "$var"
, powłoka będzie traktowana hello world
jako jedna jednostka i touch
utworzy tylko jeden plik. Ważne jest, aby zrozumieć, że dzieje się tak tylko z powodu działania powłok.
W przeciwieństwie do tego, find
nie cierpi z powodu takiego zachowania, ponieważ polecenia są przetwarzane przez find
siebie i wykonywane przez execvp()
wywołanie systemowe, więc nie ma w tym żadnej powłoki. Podczas gdy nawiasy klamrowe mają specjalne znaczenie w powłokach, ponieważ pojawiają się w środku find
polecenia, a nie na początku, w tym przypadku nie mają specjalnego znaczenia dla powłoki. Oto przykład. Utwórzmy kilka trudnych nazw plików i spróbuj przekazać je jako argument do stat
polecenia.
$ 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
Jak widać, stat
doskonale odbiera trudne nazwy plików find
, co jest jednym z głównych powodów, dla których jest zalecane do użycia w przenośnych skryptach, a szczególnie przydatne, gdy przeglądasz drzewo katalogów i chcesz zrobić coś z nazwami plików, które mogą mieć znaki specjalne w nich. Dlatego nie jest konieczne cytowanie nawiasów klamrowych dla poleceń wykonywanych w find
.
To inna historia, kiedy angażuje się Shell. Czasami musisz użyć powłoki do przetworzenia nazwy pliku. W takim przypadku cytowanie będzie miało znaczenie, ale ważne jest, aby zdawać sobie sprawę, że nie ma problemu ze znalezieniem - to powłoka dzieli słowa.
$ 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
Więc kiedy cytujemy w powłoce , to zadziała. Ale znowu, to ważne dla powłoki, nie find
.
$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;
regular empty file
regular empty file
regular empty file
/some/path
mówi, od czego zacząć, ale nic nie mówi, czego szukać. To samo w połączonej odpowiedzi. Co dla mnie działafind /some/path -name xac -print0 -quit | grep -qz . && echo found
. Przegapiłem coś?