web-dev-qa-db-ja.com

検索コマンドの '{}'と{}の違いは?

documentation では、両方の使い方がわかります。

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

find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \
18
tarabyte

bashシェルの場合、'{}'および{}は交換可能です。これは、すべてのシェル(fishなど)に当てはまるわけではありません。

引数を一重引用符で囲むと、中括弧をfindに送信する必要があることが明示的に示されます。使用法によっては、bashシェルが中括弧の内容を置き換える場合があります。

以下に示すように、bashは空の括弧を置き換えず、コマンドに渡されます。 findコマンドの場合、それは重要ではありません。

$ echo {}
{}

$ echo {1}
{1}

$ echo {1,3}
1 3

$ echo '{1,3}'
{1,3}
24
Steven

ほとんどのユーザー(特にPOSIXシェルを使用しているユーザー)にとって、違いはありません。

GNU findのマニュアルページの例のセクションによると:

中括弧は、シェルスクリプトの句読点として解釈されないように、一重引用符で囲まれていることに注意してください。

GNUのmanページの作者は注意を怠っていますが、manページのすべての例が中括弧を引用しているわけではないことに注意してください。これら examples公式からGNUドキュメントを探す 引用符も省略します。

POSIX/Single UNIX Specificationの例 では、-execオプションと一緒に使用すると、中括弧は引用符なしになります。

POSIXシェルでは、 パラメーター展開 は、中括弧で囲まれた特別なパラメーターがある場合にのみ発生します–ただし、空の中括弧では発生しません。

Bashシェルには(移植性のない)機能として 中括弧の拡張 が含まれていますが、そのようなパターンは拡張されるだけです中括弧またはドットが中括弧内に含まれている場合。 Bashは コマンドのグループ化 にも中括弧を使用しますが、実際にis中括弧内にコマンドのグループがない限りこれは発生しません。

最後に、shdash、およびtcshfind -exec ls -l {} \;を実行しようとしましたが、これらのシェルのいずれも{}を他のものに拡張しませんでした。他の人が指摘したように、fishシェルは{}を特別に扱いますが、これはPOSIXシェルではありません(作成者とユーザーが利点と考えている)。それは中括弧を引用しても害はありませんですが、魚のシェルを使用しない怠惰なタイピストは、それらを省略したことについて罪悪感を抱いてはなりません。

9

ほとんどすべてのシェルインタープリターが利用可能であるため、'{}'{}の間にまったく違いはありません。

一重引用符は通常、埋め込まれた文字列が他の何かによって置換されるのを防ぐために使用されます。次に例を示します。

  • 'a b'は単一の3文字パラメーターであり、2つの単一文字パラメーターとなる引用符は含まれません。
  • '$b'は、文字通りドル記号の後に文字bが続きます。b変数に含まれるものは何でもない引用符がありません。
  • '!!'は引用符で囲まれていない間は文字通りの感嘆符であり、一部のインタラクティブシェルでは、履歴に入れられた最後のコマンドに拡張されます
  • '*'は文字通りのアスタリスクであり、引用符で囲まれていない場合は、現在のディレクトリ内の非表示になっていないファイル名のリストに置き換えられます。

POSIX標準またはメインストリームシェル(sh(Bourne)、kshbashashdashzshcshtcsh{}を他の何かに展開します。引用符は必要ありません。

ただし、 fish という名前のエキゾチックなシェルがあり、{}が空の文字列として展開されます。例:

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

これがおそらく、GNU findドキュメントが引用符または円記号による解釈から{}を保護することを提案している理由です。

9
jlliagre

これはシェルの構文に依存します。疑わしい場合は、エコーしてください。

これを実行

echo '{}'

この。

echo {}

それらが同じ出力を生成する場合、シェルの答えは「はい」です。他の人が指摘しているように、それは少なくともバッシュではイエスであり、魚ではノーです。出力は、特定のコマンドのマンページを参照する必要があるものです。


便利な場合は、コマンドライン全体の前にechoを付けて、シェルが実際に呼び出すactualコマンドとそのすべての引数を確認することもできます。ただし、コマンドと引数で構成されるリストは文字列の真の配列であり、それぞれが空または空白である可能性がありますが、echoはスペースで区切られたリストとしてあいまいに出力することに注意してください。

この少し冗長なechoコマンドで確認できるように(guillemetで引用された引数を表示)、

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

コマンドラインでこれを入力し、

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

これはbashすることを意味します:

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

そしてこれは魚です:

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

一般的なアドバイスとして、引用することは決して痛いことではありません。

6
user2394284