Strona man dla GNU find stwierdza:
-exec command ; [...] 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.
To od człowieka do find
(GNU findutils) 4.4.2.
Teraz przetestowałem to za pomocą bash i dash i oba nie muszą {}
być maskowane. Oto prosty test:
find /etc -name "hosts" -exec md5sum {} \;
Czy istnieje skorupa, dla której naprawdę muszę zamaskować aparat ortodontyczny? Zauważ, że nie zależy to od tego, czy znaleziony plik zawiera puste (wywołane z bash):
find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \;
/home/stefan/Ubuntu One
Zmienia się, jeśli znaleziony plik zostanie przekazany do podpowłoki:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d {}' \;
ls: cannot access /home/stefan/Ubuntu: No such file or directory
ls: cannot access One: No such file or directory
które można rozwiązać przez:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "$0"' {} \;
W odróżnieniu:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "{}"' \;
/home/stefan/Ubuntu One
ale nie o tym mówi strona podręcznika, prawda? Która skorupa traktuje {}
w inny sposób?
Odpowiedzi:
Podsumowanie : Jeśli kiedykolwiek istniała powłoka, która się rozszerzyła
{}
, to teraz są to naprawdę stare, starsze rzeczy.W powłoce Bourne'a i w powłokach zgodnych z POSIX nawiasy klamrowe (
{
i}
) są zwykłymi znakami (w przeciwieństwie(
do,)
które są separatorami słów, takimi jak;
i&
,[
i]
które są znakami globowania). Wszystkie poniższe ciągi znaków powinny być drukowane dosłownie:Słowo składające się z jednego nawiasu klamrowego jest słowem zastrzeżonym , które jest wyjątkowe tylko wtedy, gdy jest pierwszym słowem polecenia.
Ksh implementuje rozszerzenie nawiasów jako niekompatybilne rozszerzenie powłoki Bourne'a. Można to wyłączyć za pomocą
set +B
. Bash pod tym względem emuluje ksh. Zsh implementuje również rozszerzenie nawiasu klamrowego; tam można go wyłączyć za pomocąset +I
lubsetopt ignore_braces
lubemulate sh
. Żadna z tych powłok nie rozszerza się{}
w żadnym wypadku, nawet jeśli jest to podciąg słowa (np.foo{}bar
), Ze względu na powszechne użycie w argumentach dofind
ixargs
.Single Unix v2 zauważa, że
Uwaga ta została upuszczona w kolejnych wersjach standardu; te przykłady
find
mają nienotowanych zastosowań{}
, podobnie jak przykłady dlaxargs
. Tam mogły{}
być cytowane historyczne muszle Bourne'a , ale do tej pory byłyby to naprawdę stare systemy starszego typu.Implementacje csh, które mam pod ręką (OpenBSD 4.7, BSD csh na Debianie , tcsh) rozwijają
{foo}
się,foo
ale pozostawiają w{}
spokoju.źródło
bash
(patrz$BASH_VERSION
). Ekspansja nawiasów klamrowych jest bardzo żywa i dobrze.{}
Składnia pochodzicsh
, ale{}
rozszerzony na pusty ciąg. Nowsze powłoki rozpoznają, że to nonsens, ale wciąż istnieją pewne starecsh
.{}foo
rozwinąłby się dofoo
, ale{}
rozwinąłby się do{}
(z wyjątkiem sytuacji, gdy znajduje się w backticks, ale cytowanie nie pomogło) i został udokumentowany jako taki. Sprawdziłem to pod kątem csh 2BSD (pierwsze wydanie), 2.79BSD, 2.8BSD i 2.11BSD.{}
Musiały być cytowany w wersjifish
skorupy przed 3.0.0.I w powłoce rc (również
akanga
opartej narc
, ale niees
):Prawdopodobnie nie są to powłoki, które autorzy dokumentacji GNU mieli na myśli, pisząc ten tekst, odkąd
fish
został wydany po raz pierwszy w 2005 r. (Podczas gdy ten tekst lub podobny był już w 1994 r.) Irc
nie był pierwotnie powłoką uniksową.Istnieją pogłoski o niektórych wersjach
csh
(powłoki, która wprowadziła rozszerzenie nawiasów klamrowych) wymagających tego. Trudno jednak przypisać je tym, ponieważ pierwsza wersjacsh
2BSD tego nie zrobiła. Tutaj, jak przetestowano w emulatorze PDP11:A strona podręcznika 2BSD
csh
wyraźnie stwierdza :Byłbym więc bardzo dziwny, gdyby później złamała go kolejna wersja csh lub tcsh.
Mogło być obejście niektórych błędów w niektórych wersjach. Nadal z tym cBS 2BSD (to samo w 2.79BSD, 2.8BSD, 2.11BSD):
Cytowanie nie pomaga jednak:
Możesz podać całe zastąpienie polecenia:
Ale to przekazuje jeden argument do tego zewnętrznego echa.
W
csh
lubtcsh
, musisz podać cytat,{}
gdy nie jest on sam, jak w:(chociaż tego rodzaju
find
użycie nie jest przenośne, ponieważ niektórefind
rozszerzają się tylko{}
wtedy, gdy są same).źródło
Jednym słowem
csh
.bash
a inne współczesne powłoki rozpoznają, że użytkownik prawdopodobnie nie prosi o rozszerzenie null nawiasu klamrowego. (Moderncsh
jest w rzeczywistościtcsh
i może również{}
rozsądnie obsługiwać .)źródło
csh
. Nie wszyscy używają narzędzi GNU w systemie Linux; w rzeczywistości dość często instaluje się je na starszych komercyjnych systemach uniksowych, których pakiety poleceń są ograniczone. (Wymianacsh
na tych systemach jest mniej prawdopodobna, ponieważ skrypty systemowe mogą polegać na osobliwościach oryginałucsh
, a nawet gdyby wszyscy użytkownicy byli skonfigurowani do korzystania z nowszej wersjicsh
,root
prawie na pewno musiałaby pozostać w pakiecie).pdksh
robi to dobrze ... chociaż prawidłowa odpowiedź na to pytanie brzmi prawdopodobnie „ksh
FOSS”...
dla ksh93, bash i zsh). Tylko (t) csh rozwija{foo}
sięfoo
, a nawet pozostawia w{}
spokoju (przynajmniej na ostatnich BSD).