シェルスクリプトでファイル名を一括変換したり、ファイル移動したりしたいが
該当ファイルにスペースが入っていて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は更新時刻の取得もできたりするので、視察場所毎にリネームしたりとか応用は色々と考えられます。