Die Manpage für GNU find lautet:
-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.
Das ist vom Mann bis find
(GNU findutils) 4.4.2.
Jetzt habe ich dies mit Bash und Dash getestet, und beide müssen nicht {}
maskiert sein. Hier ist ein einfacher Test:
find /etc -name "hosts" -exec md5sum {} \;
Gibt es eine Muschel, für die ich die Zahnspangen wirklich maskieren muss? Beachten Sie, dass es nicht davon abhängt, ob die gefundene Datei ein Leerzeichen enthält (wird von bash aufgerufen):
find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \;
/home/stefan/Ubuntu One
Dies ändert sich, wenn die gefundene Datei an eine Subshell übergeben wird:
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
was gelöst werden kann durch:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "$0"' {} \;
im Kontrast zu:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "{}"' \;
/home/stefan/Ubuntu One
Aber darum geht es doch nicht in der Manpage, oder? Also, welche Muschel behandelt {}
auf eine andere Art und Weise?
Antworten:
Fazit : Wenn es jemals eine Shell gab, die erweitert wurde
{}
, ist sie mittlerweile wirklich alt.In dem Bourne - Shell und in POSIX-compliant shells, Zahnspange (
{
und}
) sind gewöhnliche Zeichen ( im Gegensatz zu,(
und)
die Worttrennzeichen sind wie;
und&
und[
und]
die Globbing Zeichen). Die folgenden Zeichenfolgen sollen alle wörtlich gedruckt werden:Ein Wort, das aus einer einzelnen geschweiften Klammer besteht, ist ein reserviertes Wort . Dies ist nur dann etwas Besonderes, wenn es das erste Wort eines Befehls ist.
Ksh implementiert die Klammererweiterung als inkompatible Erweiterung der Bourne-Shell. Dies kann mit ausgeschaltet werden
set +B
. Bash emuliert in dieser Hinsicht ksh. Zsh implementiert auch die Klammererweiterung. dort kann es mitset +I
odersetopt ignore_braces
oder ausgeschaltet werdenemulate sh
. Keine dieser Shells wird{}
auf jeden Fall erweitert, auch wenn es sich um eine Teilzeichenfolge eines Wortes handelt (z. B.foo{}bar
), da sie häufig in Argumenten fürfind
und verwendet wirdxargs
.Single Unix v2 merkt das an
Diese Notiz wurde in nachfolgenden Versionen des Standards entfernt. Die Beispiele für
find
haben nicht zitierte Verwendungen von{}
, wie auch die Beispiele fürxargs
. Es mag historische Bourne-Muscheln gegeben haben, in denen{}
zitiert werden musste, aber sie wären inzwischen wirklich alte Legacy-Systeme.Die csh-Implementierungen, die ich zur Hand habe (OpenBSD 4.7, BSD csh unter Debian , tcsh), erweitern sich alle, lassen
{foo}
sichfoo
aber in{}
Ruhe.quelle
bash
(siehe$BASH_VERSION
). Die Strebenerweiterung ist sehr lebendig und gut.{}
Syntax stammt voncsh
, wurde jedoch{}
auf die leere Zeichenfolge erweitert. Neuere Shells erkennen, dass das unsinnig ist, aber es gibt immer noch einige altecsh
s da draußen.{}foo
würde erweitern auffoo
,{}
würde aber erweitern auf{}
(außer bei Backticks, aber Zitieren würde nicht helfen) und wurde als solches dokumentiert. Ich habe es für die csh von 2BSD (erste Veröffentlichung), 2.79BSD, 2.8BSD und 2.11BSD verifiziert.Das
{}
musste in Versionen derfish
Shell vor 3.0.0 zitiert werden .Und in der RC-Shell (auch
akanga
basierend aufrc
, aber nichtes
):Das sind wahrscheinlich nicht die Shells, an die die Autoren dieser GNU-Funddokumentation gedacht hatten, als sie diesen Text geschrieben haben, seit er
fish
2005 zum ersten Mal veröffentlicht wurde (während dieser Text oder ähnliches bereits 1994 da war) undrc
ursprünglich keine Unix-Shell waren.Es gibt einige Gerüchte, dass einige Versionen
csh
(der Shell, die die Klammererweiterung eingeführt hat) dies erfordern. Aber es ist schwer, diese zu würdigen, seitdem die erste Veröffentlichung voncsh
in 2BSD dies nicht getan hat. Hier, wie in einem PDP11-Emulator getestet:Und in der Manpage von 2BSD heißt es
csh
eindeutig :Ich würde es sehr seltsam finden, wenn eine nachfolgende Version von csh oder tcsh das später kaputt machen würde.
Es hätte sein können, dass in einigen Versionen einige Fehler behoben wurden. Immer noch mit dieser 2BSD csh (das ist dasselbe in 2.79BSD, 2.8BSD, 2.11BSD):
Das Zitieren hilft jedoch nicht:
Sie könnten die gesamte Befehlsersetzung zitieren:
Aber das ist ein Argument für dieses äußere Echo.
In
csh
odertcsh
müsstest du das zitieren,{}
wenn es nicht alleine ist wie in:(obwohl diese Art der
find
Nutzung nicht portabel ist, da einigefind
s nur erweitert werden,{}
wenn sie für sich alleine sind).quelle
Mit einem Wort
csh
.bash
und andere moderne Shells erkennen, dass der Benutzer wahrscheinlich nicht nach einer Null-Klammer-Erweiterung fragt. (Moderncsh
ist eigentlichtcsh
und kann{}
mittlerweile auch vernünftig umgehen .)quelle
csh
. Nicht jeder führt GNU-Dienstprogramme unter Linux aus. In der Tat ist es durchaus üblich, sie auf älteren kommerziellen Unix-Systemen zu installieren, deren Befehle begrenzt sind. (Austauschcsh
auf diesen Systemen ist es weniger wahrscheinlich, weil Systemskripte auf den Eigentümlichkeiten des Originals berufen kanncsh
, und auch wenn Benutzer alle konfiguriert wurden , ein neuen zu verwendencsh
,root
müßte mit ziemlicher Sicherheit die gebündelte Version bleiben.)pdksh
das Richtige tut ... obwohl die richtige Antwort auf das wahrscheinlich ist „realksh
ist FOSS in diesen Tagen“...
für ksh93, bash und zsh). Nur (t) csh dehnt{foo}
sich ausfoo
und lässt es auch{}
alleine (zumindest bei aktuellen BSDs).