ファイル名を連番にしてくれるスクリプトをつくろう!

2018.03.14

土曜日, 10. 3月 2018 08:39午後 更新

よりシンプルなスクリプトができたので, この記事を大幅に更新しました

画像の整理などをしていて,画像ファイル名を連番にしたいと思ったことは無いだろうか. 例えば,000.jpg, 001.jpg, 002.jpgというようにだ.windowsではそういうことをしてくれるソフトがあったが,linuxではなかった.

私が見つけられなかっただけかも知れないが.ならばシェルスクリプトを利用して自作してしまおう!せっかくlinuxを使っているんだ.UNIXコマンドとシェルスクリプトを利用すれば,わざわざプログラミングをしなくても意外と簡単にできてしまうのだ.

方針

というわけで,早速ソースコードを見てみよう!

プログラム

スクリプト

renban.sh

#!/bin/bash

cnt=0
extension=${1}

if [ $# -eq 0 ];
then
    echo "拡張子を入力して下さい" >&2
    exit 1
fi

for file in `ls -p | grep ".${extension}$" | sort`
do
    num=`printf "%05d" ${cnt}`

    echo "${file} -> ${num}.${extension}"
    mv ${file} ${num}.${extension}

    cnt=$((cnt + 1))
done

仕様

./rename.sh 拡張子

解説

if [ $# -eq 0 ];
then
    echo "拡張子を入力して下さい" >&2
    exit 1
fi

このif文で渡された引数の数が0かどうかを確認する. もし0であれば拡張子が指定されていないということなのでエラー出力をして終了する. そうでなければif文全体を無視して次に進む.


for file in `ls -p | grep ".${extension}$" | sort`

このfor文の右側について説明しよう.

ls -p

lsコマンドで-pオプションを使うと, 表示されるものがディレクトリのときにその名前の語尾に/が付くようになる. つまりは表示されているのがファイルなのかディレクトリなのかが明示的にわかるようになる.

grep ".${extension}$"

このgrep文によって, 表示名のが".拡張子"で終わっているもののみを表示することができる. ここでディレクトリは必然的に連番化の対象から外れることになる. ここではディレクトリは語尾が/で表させるためである.


続いてfor文の中身に移ろう.

for file in `ls -p | grep ".${extension}$" | sort`
do
    num=`printf "%05d" ${cnt}`

    echo "${file} -> ${num}.${extension}"
    mv ${file} ${num}.${extension}

    cnt=$((cnt + 1))
done
num=`printf "%05d" ${cnt}`

ここでは, printf関数でループカウンタであるcnt変数の値を5桁表示に変換している. cntが5桁よりも小さければ, 大きい桁の部分が全部0で埋まるように表示される. 例えば cnt = 123 なら, num = 00123 と表示されることになる.

なぜこのような0埋めをしているのかというと, 連番ファイルをソートするときには辞書順にソートされるからである. もし0埋めされていなければ,

1.png
2.png
5.png
12.png
13.png
25.png

という名前のファイルがあったときに,

1.png
12.png
13.png
2.png
25.png
5.png

のようにソートされてしまうのである. だからこれを防ぐために0埋めをしているわけなのである.

echo "${file} -> ${num}.${extension}"

ここでは変換処理中の様子を表示している.

cnt=$((cnt + 1))

これはbashで使えるのテクニックのひとつでループカウンタのcntの値を1だけ増加する処理である. c言語とかのx += 1と同じようなものである.