Różnica między „{}” a {} w poleceniu find?

18

W dokumentacji widzę użycie na dwa sposoby:

find . -type f -exec file '{}' \;

find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \
tarabajt
źródło
4
Pewnie wydaje się, że nie ma to nic wspólnego z funkcją find, command, a zamiast tego ma związek z poprawnym cytowaniem wywoływanego polecenia.
Zoredache,
1
Spróbuj z rybą, a nie bash.
Charles Duffy,

Odpowiedzi:

24

Do bashpowłoki '{}'i {}są wymienne. Nie jest tak w przypadku wszystkich powłok (takich jak fish).

Umieszczenie argumentu w pojedynczych cudzysłowach wyraźnie wskazuje, że nawiasy klamrowe powinny zostać wysłane do find. W zależności od użycia powłoka bash czasami zastępuje zawartość nawiasów klamrowych.

Jak widać poniżej, bash nie zastępuje pustych nawiasów i są przekazywane do polecenia. Dla findpolecenia to nie ma znaczenia.

$ echo {}
{}

$ echo {1}
{1}

$ echo {1,3}
1 3

$ echo '{1,3}'
{1,3}
Steven
źródło
4
Nie ma znaczenia z bash. Ma znaczenie dla ryb.
Charles Duffy,
1
Chciałbym zamienić " are interchangeable"z " are interchangeable in some shells, not in all of them. ALWAYS use the single quotes to make sure they get passed as-is to the find command"(dobrych nawyków rozpoczyna upewniając użyć właściwą drogę nawet jeśli zdarzy się (zawsze) będzie na systemie, który pozwala na dwuznaczne jeden?)
Olivier Dulac
9

Przy prawie wszystkich dostępnych interpretatorach powłok nie ma absolutnie żadnej różnicy między '{}'i {}.

Pojedyncze cudzysłowy są zwykle używane do ochrony osadzonego ciągu przed zastąpieniem go przez coś innego, na przykład:

  • 'a b' to parametr składający się z trzech znaków, bez cudzysłowów, które byłyby dwoma parametrami z jednym znakiem
  • '$b' to dosłownie znak dolara, po którym następuje litera b, bez cudzysłowu, który byłby czymkolwiek, co zawiera zmienna b, i być może nic, gdyby nie była ustawiona
  • '!!' są wykrzyknikami w literaturze, gdy nie są cytowane, a przy niektórych interaktywnych powłokach rozwiną się do ostatniego polecenia w historii
  • '*' jest literą literalną, bez cudzysłowu zastąpiłaby ją lista ukrytych nazw plików w bieżącym katalogu.

Ponieważ ani ze standardem POSIX ani muszli nurtu ( sh(Bourne), ksh, bash, ash, dash, zsh, csh, tcsh) rozwinąć {}się do czegoś innego, cytaty nie są wymagane.

Istnieje jednak egzotyczna powłoka o nazwie fish, która rozwija się {}jako pusty ciąg znaków, np .:

> ps -p %self
  PID TTY          TIME CMD
 5247 pts/1    00:00:00 fish
> echo a {} b '{}'
a  b {}

Jest to prawdopodobnie powód, dla którego finddokumentacja GNU sugeruje ochronę {}przed interpretacją za pomocą cytatów lub ukośników odwrotnych.

jlliagre
źródło
9

Dla większości użytkowników (szczególnie tych używających powłok POSIX) nie ma różnicy.

Zgodnie z sekcją Przykład strony podręcznika dla GNU find:

Zauważ, że nawiasy klamrowe są ujęte w znaki pojedynczego cudzysłowu, aby chronić je przed interpretacją jako interpunkcji skryptu powłoki.

Myślę, że autorzy strony podręcznika GNU popełniają błędy po stronie ostrożności, ale zauważam, że nie wszystkie przykłady na stronie podręcznika cytują nawiasy klamrowe. Te przykłady z oficjalnej dokumentacji znalezienia GNU również pomijają cytowanie.

W przykładach ze specyfikacji POSIX / Single UNIX nawiasy klamrowe niecytowane, gdy są używane z -execopcją.

W przypadku powłoki POSIX ekspansja parametrów występuje tylko wtedy, gdy w nawiasach znajdują się specjalne parametry - ale nie w pustych nawiasach .

Powłoka Bash zawiera rozwinięcie nawiasu jako funkcję (nieprzenośną), ale takie wzory są rozwijane tylko wtedy, gdy w nawiasach znajdują się przecinek lub kropki . Bash używa również nawiasów klamrowych do grupowania poleceń , ale nie dzieje się tak, chyba że faktycznie istnieje grupa poleceń w nawiasach klamrowych.

Wreszcie, próbowałem działa find -exec ls -l {} \;w sh, dasha tcshjednak żaden z tych muszli rozszerzono również {}na cokolwiek innego. Jak zauważyli inni, fishpowłoka traktuje {}specjalnie, ale nie jest to powłoka POSIX (co jej twórcy i użytkownicy uważają za zaletę). To nie zaszkodzi zacytować szelki ale maszynistki leniwych, którzy nie korzystają z skorupiaków nie powinien czuć się winny ich pominięcia.

Anthony G - sprawiedliwość dla Moniki
źródło
nie mylą się, starają się upewnić, że ludzie używają prawidłowego sposobu (tj. używaj '{}'zamiast {}), aby ich powłoka wysłała {}polecenie find bez interpretowania go (jak wspomniano powyżej przez @ Charles-Duffy, jeśli zdarzy się, że używasz ryb , to zinterpretuje, {}ale nie '{}', więc musisz użyć tego drugiego na tej powłoce (i kilku innych!). Dlatego zawsze używaj, '{}'aby uniknąć ukąszenia przez dwuznaczność{}
Olivier Dulac
6

To zależy od składni twojej powłoki. W razie wątpliwości powtórz to!

Uruchomić to

echo '{}'

i to.

echo {}

Jeśli generują ten sam wynik, odpowiedź dla twojej powłoki brzmi: tak. Jak zauważyli inni, przynajmniej będzie tak w bashu, a nie w rybach. Dane wyjściowe są tym, do czego należy zajrzeć na stronę podręcznika danego polecenia.


Jeśli chcesz się przydać, możesz nawet prefiksować echocałą linię poleceń, aby zobaczyć rzeczywiste polecenie wraz ze wszystkimi argumentami, które faktycznie wywoła twoja powłoka. Uważaj jednak, że lista zawierająca polecenie plus argumenty to prawdziwa tablica ciągów znaków, każda być może pusta lub z białymi spacjami, ale echo wypisuje ją niejednoznacznie jako listę oddzieloną spacjami.

Jak można zweryfikować za pomocą tej nieco bardziej szczegółowej komendy echo (pokazującej argumenty cytowane w guillemet),

#!/bin/sh
for a in "$@"; do
    printf '«%s» ' "$a"
done
echo ''

wpisując to w wierszu poleceń,

find 'My Documents and Settings' -type f -exec file {} \;

oznacza to bash:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «{}» «;»

a to u ryb:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «» «;»

Jako ogólna rada, nigdy nie boli cytować.

użytkownik2394284
źródło