シェルスクリプトで複数ファイルを一括リネームする方法

シェルスクリプトを使って複数ファイルを一括リネームする方法を解説します.

例えば, ディレクトリにapple1, apple2, apple3, apple4, apple5というファイルがあり, これをorange1, orange2, orange3, orange4, orange5というファイル名に変えたいときには, 次のようにします.


$ ls
apple1 apple2 apple3 apple4 apple5
$ for f in apple* ; do ; mv $f ${f/apple/orange} ; done
$ ls
orange1 orange2 orange3 orange4 orange5
            

さて, ここでリネームを実際に行っているのは, 3行目になります. 1行になっていますが, これを複数行になおしてみると, 次のようになります.


for f in apple*
do
    mv $f ${f/apple/orange}
done
            

apple*の部分は, この作業ディレクトリにおいて, apple1 apple2 apple3 apple4 apple5と同様の意味をもちます. つまり, apple1~apple5のそれぞれが変数fに入れられて, for文が回っていきます.

3行目では, リネームをするために, mvが呼ばれ, また, 変数fに対して文字列置換が行われています. 例えば, fにapple3が入っている時には, 3行目は,


mv apple3 orange3
            

のようになります. これが全てのapple1~apple5ファイルに適応されるため, ファイルは一括リネームされます.

文字列置換に関しては, よろしければ「シェルスクリプト入門」を参考になさって下さい.

さて, この一貫の処理をスクリプトにしますと, 以下のようになります.


#!/bin/bash

if [ $# -lt 3 ]
then
	echo "変更前の文字列, 変更後の文字列, 変更したいファイル名を入力して下さい."
	exit 1
fi

args=$*
extra_args="$1 $2"
files=${args#$extra_args}

for f in $files
do
	mv $f ${f/$1/$2}
done
            

[訂正] 文字列置換は, /bin/shでは行えなかったかもしれません. 上記コード内で一行目を#!/bin/shとしていたため, 訂正致します. 正しくは, 一行目を#!/bin/bashとしてください.

まず, 3行目から7行目までは, エラー処理です. 引数が3つより少ないとエラー文を吐いて終了します.

9行目から11行目で, 全ての引数から, "変更前の文字列", と"変更後の文字列"を抜き取っています. 少し詳しく言いますと, 9行目で変数argsに全ての引数を代入しています. 10行目で1つ目と2つ目の引数に空白を挟んだ文字列を作ってextra_argsという変数に代入, 11行目でfilesという変数に変数argsから変数extra_argsの文字列を削除したものを代入しています. 以上の操作で, 3つ目以降の引数, つまり変更したいファイル名を全てfilesという変数に入れることが出来ました.

13行目から, 16行目は上で解説した通りです. では, 使ってみます.


$ ls
file1     file2     file3     file4     file5     rename.sh
$ ./rename.sh file doc file*
$ ls
doc1      doc2      doc3      doc4      doc5      rename.sh
            

使うときには, 実行権を付けることを忘れないようにしましょう.