使用例 (不自然!): .mp3 ファイルの名前を .txt に変更します。
次のようなことができるようになりたいです
find -name '*.mp3' -print0 | xargs -0 -I'file' mv file ${file%.mp3}.txt
これはうまくいかないので、find
の出力を に通すことに頼りましたsed -e 's/.mp3//g'
。
ただし、少しハックなようです。通常の bash${x%y}
構文を使用する方法はありますか?
いいえ、変数はシェルではなくxargsプログラムによって展開されるxargs -0 -I'file' mv file ${file%.mp3}.txt
ため、機能しません。file
実際、それを変数として参照することは完全には正しくありません。xargsのマニュアルでは「replace-str」と呼ばれています。
更新:xargsとbashだけを使用する(sedなどは使用しない)には、もちろんxargsにbashプロセスを開始させて、必要な置換を実行できます。
find -name '*.mp3' -print0 | xargs -0 bash -c \
'while [ -n "$1" ]; do mv "$1" "${1%.mp3}.txt" ; shift; done;' "bash"
別の提案を追加するために、シェルの置換メカニズムを使用していませんが、代わりに sed を使用しています。
find -name '*.mp3' -print |
sed -e 's/\.mp3$//' -e "s/.*/mv '&\.mp3' '&\.txt'/" |
sh
つまり、mv
ファイル名ごとにコマンド ラインを作成し、結果を に渡しますsh
。
いずれかのファイルのファイル名にアポストロフィ (一重引用符) が含まれている場合、これは失敗します。私は主に、「xargs しか持っていない場合、すべての問題が釘のように見える」症候群に対抗するためにこれを投稿します。
すべての sed の構文がまったく同じというわけではありません。特に、古い SunOS で複数の -e 引数を指定できるかどうかは 100% 確信が持てません (XPG 互換の sed を のようなもので探してください/usr/ucb/blah/barf/vomit/xpg4/bin/sed
) 。
GNU Parallel がインストールされている場合:
find -name '*.mp3' -print0 | parallel -0 mv {} {.}.txt
ファイル名に \n (改行) が含まれていない場合、これも機能します。
find -name '*.mp3' | parallel mv {} {.}.txt
GNU Parallel の詳細については、イントロ ビデオをご覧ください http://www.youtube.com/watch?v=OpaiGYxkSuQ
find . -type f -name '*.mp3' | while read -r F
do
mv "$F" "${F%.mp3}.txt"
done
バッシュ 4+
shopt -s globstar
shopt -s nullglob
for file in **/*.mp3
do
mv "$file" "${file%.mp3}.txt"
done
perl rename.pl 's/\.mp3$/.txt/' *.mp3
# Or **/*.mp3 for zsh and bash with specific settings set, for a recursive
# rename.
http://people.sc.fsu.edu/~jburkardt/pl_src/rename/rename.html