TOC
割とあるあるな話だと思います。こんなディレクトリがあるとして、
$ ls
1.jpg 10.jpg 2.jpg 3.jpg 4.jpg 5.jpg 6.jpg 7.jpg 8.jpg 9.jpg
連番が振られていると、辞書順で昇順にソートしたファイル名を表示すると、1文字目で並ぶので1,10,2,3と並びます。
GNUのls
はバージョニングスキーム順にソートする-v
オプションを使用すると、上記のような場合でも1,2,3,…,10の順に表示できます。
-v natural sort of (version) numbers within text
$ ls -v
1.jpg 2.jpg 3.jpg 4.jpg 5.jpg 6.jpg 7.jpg 8.jpg 9.jpg 10.jpg
処理結果をファイルに出して別プロセスに食わせる等する場合はこれで対応可能ですが、コマンドの実行時に*で渡したい時がないでしょうか。私はものすごくあります。
ということで、ファイル名の前からゼロ埋めをした連番でリネームしていきます。参考にしたのはこちら。
$ ls -v1 | awk '{ printf("%s %02d.jpg\n", $1, $1) }' | xargs -n 2 mv
mv: '10.jpg' and '10.jpg' are the same file
$ ls
01.jpg 02.jpg 03.jpg 04.jpg 05.jpg 06.jpg 07.jpg 08.jpg 09.jpg 10.jpg
ここで取っている手法は少しトリッキーです。
- 10.jpgとかの元々2桁の番号のファイルはmvに渡す2つのファイル名が同じになるので、mv自体は実行されない(所望の動作にはなる)
- printfでプレースホルダに置換する際に%dにファイル名を渡すことで数字部分だけを出力する”甘え”を使っているので、拡張子をその後で指定している
- awkに渡しているファイル名がmvの対象になるので、希望しないファイル(拡張子が違うなど)が含まれる場合はlsの出力結果でフィルタリングが必要。しないとファイル名はともかく拡張子が変わってしまう
3桁にしたい場合はprintfのプレースホルダを%03dにします。
$ ls -v1 | awk '{ printf("%s %03d.jpg\n", $1, $1) }' | xargs -n 2 mv
$ ls
001.jpg 003.jpg 005.jpg 007.jpg 009.jpg
002.jpg 004.jpg 006.jpg 008.jpg 010.jpg
スポンサーリンク
comments powered by Disqus