Co oznacza „{} \;” w poleceniu Linuksa?

37

Czasami widzę następujące polecenie:

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

Zostałem poproszony o wykonanie tego.

Co to {} \;znaczy tutaj?

codeofnode
źródło
1
-name *jest zbędny.
Kevin
3
Sprawdź także objaśnienia dotyczące innych rodzajów pytań takich jak ten. Oto wynik Twojej komendy. .
Glutanimate,
8
-name *jest gorszy niż zbędny. Ponieważ *nie jest cytowany, powłoka rozwija go do listy nazw plików w bieżącym folderze, a spacje są niepoprawnie traktowane, co prowadzi do nieoczekiwanych wyników lub komunikatu o błędzie. Dodatkowo findma wiele funkcji, jedną z nich jest wyświetlanie listy plików; pozwala to uniknąć konieczności używania -exec. Np. Możesz użyć find . -printlub find . -ls. Wreszcie, istnieją dwa sposoby, aby uciec średnik: albo jak to było z ukośnik, \;lub podając: ';'. Używaj tego, z czym czujesz się bardziej komfortowo.
Paddy Landau

Odpowiedzi:

48

Jeśli uruchamiasz findz exec, {}rozwija się do nazwy pliku każdego znalezionego pliku lub katalogu find(tak, że lsw twoim przykładzie dostaje się każdy znaleziony plik jako argument - pamiętaj, że wywołuje on lsdowolną inną komendę podaną raz dla każdego znalezionego pliku).

Średnik ;kończy polecenie wykonane przez exec. Trzeba go uciec, \aby pocisk, który w nim biegnie find, nie traktował go jako własnego znaku specjalnego, lecz przekazał go find.

Więcej informacji znajdziesz w tym artykule .


Ponadto, findzapewnia pewną optymalizację z exec cmd {} +- kiedy prowadzony tak, findDokleja znaleźć pliki na końcu polecenia, a nie powołując go raz na plik (tak, że polecenie jest uruchamiane tylko raz, jeśli to możliwe).

Różnica w zachowaniu (jeśli nie pod względem wydajności) jest łatwo zauważalna, jeśli jest uruchamiana lsnp

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

Zakładając, że masz kilka jpgplików (z wystarczająco krótkimi ścieżkami ), wynikiem jest jeden wiersz na plik w pierwszym przypadku i standardowe lszachowanie wyświetlania plików w kolumnach dla tego drugiego.

moon.musick
źródło
1
Myślę, że byłoby korzystne, aby przeciwstawić \;się +.
Kevin
Czym się różni find . -name * | ls -a -?
András Hummer,
@DrH Chodzi o to, aby shell nie wykonywał interpretacji symboli zastępczych, ale raczej przekazywał wyrażenie symboli zastępczych do find. Ponadto dane wyjściowe lsw tym przypadku najwyraźniej nie zależą od danych wejściowych - bez względu na to, czego używam jako filtr find, lspo prostu wyświetla zawartość katalogu roboczego i to wszystko. Sprawdzić na przykład find ~ -iname '*.jpg' -exec ls -a {} \;vs find ~ -iname '*.jpg' | ls -a.
moon.musick
@DrH lub nawet echo 'foo' | ls -a.
moon.musick
@ moon.musick, uważam, że nie sprawdziłeś się -w swoim ls -a -poleceniu podczas testowania tego, o co pytał @ dr-h.
Daniel Llewellyn
20

Z strony podręcznika dla findpoleceniaIkona strony :

-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.

Oto wyjaśnienie:

{}oznacza „wynik find”. Jak w „cokolwiek findznaleziono”. findzwraca ścieżkę szukanego pliku, prawda? Więc {}zastępuje go; jest to symbol zastępczy dla każdego pliku, który findlokalizuje polecenie (pochodzi stąd ).

Ta \;część mówi w zasadzie find„OK, skończyłem z poleceniem, które chciałem wykonać”.

Przykład:

Powiedzmy, że jestem w katalogu pełnym .txtplików. Następnie uruchamiam:

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

Pierwsza część find . -name *.txtzwraca listę .txtplików. Druga część, -exec cat {} \;wykona catpolecenie dla każdego pliku znalezionego przez find, tak cat file1.txt, cat file2.txti tak dalej.

Alaa Ali
źródło
4
Część *.txtnależy podać jako '*.txt'. Wynika to z faktu, że jeśli .txtw bieżącym folderze znajdują się pliki, powłoka to rozwinie, a otrzymasz nieprawidłowe wyniki lub komunikat o błędzie. find -name '*.txt' -exec cat {} \;
Paddy Landau
@Alaa Ali bardzo dobrze wyjaśnione
pushya