Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

スペース文字が入ったファイル名をxargsを使って一括変換したいとき、-0オプションを使うといいかも

シェルスクリプトでファイル名を一括変換したり、ファイル移動したりしたいが
該当ファイルにスペースが入っていてxargsがうまく動かない場合があります。
そんな時は、ヌル文字をデリミターにつかう"-0"オプションが使えるかもしれません。

実際のところ

こんな風に、iPhoneでとった写真が入ったディレクトリがあるとします。
これをimageNUM.jpgといった感じに変更するケースを考えます。

$ ls -1 iOS* 
iOS の画像 (1).jpg
iOS の画像 (2).jpg
iOS の画像.jpg
$ find iOS*  | sed "p; s/iOS の画像/image/"
iOS の画像 (1).jpg
image (1).jpg
iOS の画像 (2).jpg
image (2).jpg
iOS の画像.jpg
image.jpg

xargsには指定行を引数にとるオプションがあるので、これを使ってデリミターを改行としてやれば良さそうに感じます。
が……残念ながら、ファイル名に含まれるスペースが悪さをします。

 $ find iOS*  | sed "p; s/iOS の画像 /image/" | xargs -E '\n' -n2 mv
mv: rename iOS to の画像: No such file or directory
mv: rename (1).jpg to image(1).jpg: No such file or directory
mv: rename iOS to の画像: No such file or directory
mv: rename (2).jpg to image(2).jpg: No such file or directory
mv: rename iOS to の画像.jpg: No such file or directory
mv: rename iOS to の画像.jpg: No such file or directory

ここで、ヌル文字をデリミターにする"-0"オプションです。
まず下準備として、改行をヌル文字に変えてみましょう。
変換対象の改行がヌル文字になっているのが確認できます。

$ find iOS*  | sed "p; s/iOS\ の画像/image/" | tr '\n' '\0' | xxd 
00000000: 694f 5320 e381 aee7 94bb e583 8f20 2832  iOS ......... (2
00000010: 292e 6a70 6700 696d 6167 6520 2832 292e  ).jpg.image (2).
//(ry

あとは、"-n"オプションと"-0"オプションをつかって、mvコマンドに渡してあげるだけです。

$ find iOS*  | sed "p; s/iOS\ の画像/image/" | tr '\n' '\0' | xargs -0 -n2 mv

実行結果をみれば、意図通りファイル名が変更されています。

$ ls
image (2).jpg	image (1).jpg	image.jpg

……今回は3個程度なので有難味が薄いですが……数が多い時は絶対児童がしたほうがいいです。
findは更新時刻の取得もできたりするので、視察場所毎にリネームしたりとか応用は色々と考えられます。