GNUのmanページは、状態を見つける:
-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.
それは男からfind
(GNU findutils)までです。
これをbashとdashでテストしましたが、どちらも{}
をマスクする必要はありません。ここに簡単なテストがあります:
find /etc -name "hosts" -exec md5sum {} \;
本当にブレースをマスクする必要があるシェルはありますか?見つかったファイルに空白が含まれているかどうかには依存しないことに注意してください(bashから呼び出されます)。
find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \;
/home/stefan/Ubuntu One
見つかったファイルがサブシェルに渡されると、これは変更されます。
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
これは次の方法で解決できます。
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "$0"' {} \;
対照的に:
find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "{}"' \;
/home/stefan/Ubuntu One
しかし、それはmanページが話していることではありません、そうですか?では、どのシェルが{}
を別の方法で扱いますか?
概要:{}
を展開したシェルがあった場合、それは今では本当に古いレガシーのものです。
BourneシェルおよびPOSIX準拠シェルでは、中かっこ({
および}
)は通常の文字です((
および)
のようなWord区切り文字である;
および&
とは異なり、[
および]
はグロビング文字です)。次の文字列はすべて文字どおりに出力されることになっています。
$ echo { } {} {foo,bar} {1..3}
{ } {} {foo,bar} {1..3}
単一のブレースで構成されるワードは 予約語 であり、コマンドの最初のワードである場合にのみ特別です。
Kshは、Bourne Shellの非互換の拡張機能としてブレース拡張を実装しています。これはset +B
でオフにできます。この点で、bashはkshをエミュレートします。 Zshはブレース展開も実装しています。そこでは、set +I
、setopt ignore_braces
、emulate sh
でオフにすることができます。 find
と xargs
への引数の一般的な使用により、Wordの部分文字列({}
など)であっても、これらのシェルはいずれもfoo{}bar
を展開しません。
一部の歴史的なシステムでは、中括弧は制御演算子として扱われます。将来の標準化活動を支援するために、移植可能なアプリケーションでは、引用符で囲まれていない中括弧を使用して文字自体を表すことを避けます。 ISO/IEC 9945-2:1993規格の将来のバージョンでは、
{
と}
を個別に制御演算子として扱うことが必要になる可能性がありますが、トークン{}
は、find
{}
構文を使用しました。
このメモは、標準の後続のバージョンでは削除されました。 find
の例 は、 xargs
の例 と同様に、引用符なしで{}
を使用しています。 {}
を引用しなければならない歴史的なBourneシェルがあったかもしれませんが、それらは今では本当に古いレガシーシステムでしょう。
私が手元にあるcsh実装(OpenBSD 4.7、 DebianのBSD csh 、tcsh)はすべて{foo}
をfoo
に拡張しますが、{}
はそのままにします。
3.0.0より前のバージョンのfish
シェルでは、{}
を引用する必要がありました。
$ fish -c 'echo find -exec {} \;'
find -exec ;
そしてrcシェルでは(akanga
にもとづくrc
ではなくes
ではありません):
$ rc -c "echo find -exec {} ';'"
line 1: syntax error near '{'
これらは、fish
が最初に2005年にリリースされて以来(そのテキストまたは類似のものがすでに1994年にそこにあった一方で)、そのテキストを書いたときにGNUのドキュメントの作成者が考えていたシェルではない可能性があります)およびrc
は、もともとUnixシェルではありませんでした。
csh
(ブレース展開を導入したシェル)の一部のバージョンには、それを必要とする噂がいくつかあります。しかし、2BSDでのcsh
の最初のリリースはそうしなかったので、それらを信用するのは難しい。ここでは、PDP11エミュレータでテストされています。
# echo find -exec {} \;
find -exec {} ;
そして 2BSDのmanページcsh
は明確に述べています :
特殊なケースとして、 `{'、`}'および `{} 'はそのまま渡されます。
したがって、cshまたはtcshの後続のバージョンが後でそれを壊した場合、それは非常に奇妙だと思います。
いくつかのバージョンではいくつかのバグを回避するためでした。それでも2BSD csh(2.79BSD、2.8BSD、2.11BSDでも同じ):
# csh -x
# echo foo {} bar
echo foo {} bar
foo {} bar
# echo `echo foo {} bar`
echo `echo foo {} bar`
echo foo {} bar
foo bar
しかし、引用は役に立ちません:
# echo `echo foo '{}' bar`
echo `echo foo '{}' bar`
echo foo {} bar
foo bar
コマンド置換全体を引用できます。
# echo "`echo foo {} bar`"
echo `echo foo {} bar`
echo foo {} bar
foo {} bar
しかし、それはその外部エコーに1つの引数を渡しています。
csh
またはtcsh
では、次のように単独ではない場合、{}
を引用符で囲む必要があります。
find . -name '*.txt' -type f -exec cp {} '{}.back' \;
(そのようなfind
の使用は、一部のfind
sが{}
を拡張するだけなので、移植性がありません)。
つまり、csh
。 bash
および他の最新のシェルは、ユーザーがnullブレース展開を要求していないことを認識しています。 (モダンcsh
は実際にはtcsh
であり、{}
今までに正気に。)