Dlaczego „find -exec cmd {} +” musi kończyć się na „{} +”?

11

Przedmowa: Rozumiem różnicę między -exec {} \;& -exec {} +. Ja też nie mam problemu jako takiego , jestem po prostu ciekawy temat semantyki find.


Kiedy kończy się -execargument, ze +zamiast ;, to trzeba z tym skończyć z {} +, na przykład:

# FreeBSD find
$ find . -type f -exec cp {} /tmp +
find: -exec: no terminating ";" or "+"

# GNU find is even more cryptic:
$ find: missing argument to `-exec'

Zastosowanie ;w tych przykładach zamiast +działa dobrze (ale oczywiście robi coś innego).

Z POSIX :

-exec utility_name [argument ...] ;
-exec utility_name [argument ...] {} +

... Tylko <plus-sign>, który następuje bezpośrednio po argumencie zawierającym tylko dwa znaki „ {}”, interpunktuje koniec wyrażenia podstawowego. Inne zastosowania <plus-sign> nie będą traktowane jako specjalne.

Innymi słowy, podczas korzystania +z polecenia polecenie musi się kończyć {} +.

Dlaczego to? A dlaczego tylko z, +a nie z ;? Na początku pomyślałem, że może powinienem unikać konfliktów z nazwami plików, które zawierają +, ale nazwy plików z ;wyglądają dobrze. Trudno mi uwierzyć, że to ograniczenie jest arbitralne ...

Martin Tournoij
źródło
3
FWIW, strona POSIX również mówi, że The "-exec ... {} +" syntax adopted was a result of IEEE PASC Interpretation 1003.2 #210i w tym dokumencie znajdziesz więcej szczegółów, np .:Note that the "+" is only treated as special if it immediately follows "{}". This minimises the chances of causing problems with existing uses of "+" as an argument with "-exec".
don_crissti 15.01.15

Odpowiedzi:

5

Uzasadnienie podane w opisie POSIX:

"-exec ... {} +"Składnia przyjęty był wynikiem IEEE PASC Interpretacji 1003,2 # 210. Należy zauważyć, że jest to niezgodna zmiana normy ISO / IEC 9899: 1999. Na przykład następujące polecenie drukuje wszystkie pliki o '-'nazwie po nazwie, jeśli są zwykłymi plikami, a w '+'przeciwnym razie:

find / -type f -exec echo {} - ';' -o -exec echo {} + ';'

Zmiana unieważnia takie użycie. Mimo że poprzedni standard stwierdził, że takie użycie będzie działać, w praktyce wielu go nie obsługiwało, a programiści standardu uznali, że lepiej jest teraz stwierdzić, że nie jest to dozwolone.

Interpretacja PASC 1003.2 # 210 zawiera bardziej szczegółowe informacje na temat historii -exec … {} +. Istniał na kilku systemach uniksowych, zanim został przyjęty przez POSIX; raport wady śledzi go z powrotem do SVR4 (gdzie był w dużej mierze nieudokumentowany). Raport wady uzasadnia niezgodność zmiany jako mającą niewielki wpływ w praktyce:

Zauważ, że „+” jest traktowany jako wyjątkowy tylko wtedy, gdy bezpośrednio po „{}”. Minimalizuje to szanse na spowodowanie problemów z istniejącym użyciem „+” jako argumentu z „-exec”.

Chociaż dodanie obsługi dla -exec … {} +zepsułoby niektóre zgodne aplikacje, takie jak powyższy przykład, jest ich mniej, niż byłoby -exec … {} … +to dozwolone.

Być może innym powodem, aby ograniczyć się {}do ostatniego argumentu, jest łatwość implementacji. Jeśli {}pozwolono by w dowolnym miejscu na liście argumentów -exec, findprogram musiałby zbudować linię poleceń, kopiując argumenty statyczne, następnie część zmienną, a następnie inną część statyczną. Utrudniłoby to zbudowanie listy argumentów i uwzględnienie limitu wielkości. Trudność jest minimalna, ale realizatorzy lubią wycinać rogi. Obsługa wielu zastępowalnych instancji {}(jeśli -exec {} foo +ma działać, można logicznie oczekiwać, -exec {} foo {} +że tak samo będzie), byłaby znacznie trudniejsza.

Gilles „SO- przestań być zły”
źródło