背景
その昔iTunesなどでCDからPCに取り込んだmp3ファイルに対して、Music Source Separationやったりして遊びたいときってありますよね。
ただ、曲名って複数単語だとスペースが入っていたり、アポストロフィとしてシングルクォートが含まれていたり(No Man's Land
のような)で、コマンドライン上で使うにはあまりありがたくない文字列である場合も多いです。
とりあえず、あとあと扱いやすくするために、これらの面倒な文字を_
に置換してしまいたい、というのが今回の動機です。
私が試したケースでいうと、タイトルのようにスペースとシングルクォートだけで事足りたのですが、それ以外の場合があれば適宜コマンド上で置換対象とする文字を増やしてもらえればと思います。
(2020/09/09追記)MacまたはLinuxではrename
コマンドでよかった。Macの場合、brew
でrename
をインストールしてから実行する。
brew install rename
ls *.mp3 | rename "s/[\ \']/_/g"
(追記ここまで)
コマンド
ls *.mp3 | awk '{gsub(/\ /,"\\ ");gsub(/'\''/,"\\'\''");print;gsub(/[\ '\'']/,"_");gsub(/\\/,"");print}' | xargs -n 2 mv
処理の流れ
ちょっとだけ内容を解説します。
1. リネームさせたいファイル名を抽出する
ls *.mp3
の部分です。今回は拡張子mp3
のファイルに限定していますが、ここは任意です。
2. 変更前のファイル名と変更後のファイル名を出力する
awk '{ 〜〜 }'
の個所です。何やってるのかわからないところかと思います。
ここでは、パイプ経由で標準入力に与えられた行(ファイル名)を「編集して出力」を2回行っています。
たとえば、ho ge'ho ge.mp3
という半角スペースとシングルクォートを含むファイル名があったとします。awk
への入力に流れてきたときの流れを見やすく表現してみましょう。
{ # ho ge'ho ge.mp3
gsub(/\ /,"\\ "); # ho\ ge'ho\ ge.mp3
gsub(/'\''/,"\\'\''"); # ho\ ge\'ho\ ge.mp3
print; # ↑を出力
gsub(/[\ '\'']/,"_"); # ho\_ge\_ho\_ge.mp3
gsub(/\\/,""); # ho_ge_ho_ge.mp3
print # ↑を出力
}
処理自体は単純なのですが、エスケープまみれなせいで見づらくなってますね。
awk
では、半角スペースやバックスラッシュは\
を前につけるだけでエスケープできるのですが、シングルクォートは'\''
と、バックスラッシュを前に付けた上でさらにシングルクォートで囲む、ということをしないといけないようです。
3. awk
の出力をmv
の引数に渡して実行する
上記awk
の処理では、mv
に渡す「変更前のファイル名」と「変更後のファイル名」をそれぞれ出力しました。それらをmv
の2つの引数に渡すにはxargs
を使います。
xargs -n 2 <cmd>
で、前2つの出力を<cmd>
の引数として渡せます。つまり、この場合は最終的に
mv ho\ ge\'ho\ ge.mp3 ho_ge_ho_ge.mp3
というコマンドが実行されることになります。
おわりに
もっといいやり方ないんかいな… あったので追記した。