検索コマンド:一重引用符と二重引用符

検索コマンド:一重引用符と二重引用符

Findを使用してファイル名を変更しています。

これは働きます:find . -iname a* -exec bash -c 'x={};mv {} ${x/a/b}' \;

しかし、そうではありません: find . -iname a* -exec bash -c "x={};mv {} ${x/a/b}" \;

なぜ?

Bashで実行されます。

ありがとう

答え1

まず、次を参照してください。シェルの「...」、「...」、$'...'、および$"..."引用符の違いは何ですか?

これは働きます:find . -iname a* -exec bash -c 'x={};mv {} ${x/a/b}' \;

現在のディレクトリにで始まるファイル名がなく、aツリーのファイル名にスペースやシェル固有の文字が含まれていない場合は、はい、おそらく機能します。

しかし、そうではありません:find . -iname a* -exec bash -c "x={};mv {} ${x/a/b}" \;

この"x={};mv {} ${x/a/b}"部分は二重引用符で囲まれているため、${...}コマンドを実行する前にシェルがここで展開されます。結果文字列はシェルで設定される可能性がないため、結果文字列のみを表示できますfindx={};mv {}$x

最初のエントリでは、一重引用符が拡張を防止するため、参照してfindファイルx={};mv {} ${x/a/b}名を変更して{}実行するように要求したシェルに結果を渡します。効果があるかもしれません。


しかし、ここにはいくつかの問題があります。最初のものは引用されていません-iname a*。これは実行前にシェルからglobを拡張するため、findディレクトリにegが含まれている場合は実行するabcd.txtのとasdf.txt同じですfind . -iname abcd.txt asdf.txt。最初のファイル名はで-iname、2番目のファイル名はエラーです。

次に、たとえばツリーのどこかにあるファイル名を{}考えてみます。シェルで変更して実行します。ただし、これは目的の構文ではなく、runとコマンドで割り当てられます。このように、コードとデータを混在させることはほとんど作業できません。特に、以下を含むことができるファイル名の場合はさらにそうです。foo bar.txtfindx={};mv {} ${x/a/b}x=foo bar.txt;mv foo bar.txt ${x/a/b}fooxbar.txtすべての文字。これはまたfoo; echo doing bad things


正しい方法は、ファイル名を場所引数として内部シェルに渡し、スクリプト内の拡張子を参照することです。

だから、

find . -iname "a*" -exec bash -c 'mv "$1" "${1/a/b}"' sh {} \;

望むより:

関連情報