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}"
部分は二重引用符で囲まれているため、${...}
コマンドを実行する前にシェルがここで展開されます。結果文字列はシェルで設定される可能性がないため、結果文字列のみを表示できますfind
。x={};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.txt
find
x={};mv {} ${x/a/b}
x=foo bar.txt;mv foo bar.txt ${x/a/b}
foo
x
bar.txt
すべての文字。これはまたfoo; echo doing bad things
。
正しい方法は、ファイル名を場所引数として内部シェルに渡し、スクリプト内の拡張子を参照することです。
だから、
find . -iname "a*" -exec bash -c 'mv "$1" "${1/a/b}"' sh {} \;
望むより: