シェルスクリプトの作り方

どんなプログラムを作るか?

ここではシェルスクリプトの応用例として、複数のファイルの名前を変更する プログラムを作ってみよう。
最初は簡単なプログラムから徐々に複雑で汎用的なプログラムに作り変えてゆく。

最初のプログラム

まず、test1, test2, ... test5という名前のファイルを tmp1, tmp2, ... tmp5という名前に変えるシェルスクリプトを作ってみる。

#!/bin/csh -f
set i = 1
while($i <= 5)
	mv test$i tmp$i
	@ i ++
end
# vi rename.sh    <- 上のプログラムをrename.shという名前で作る
# ls
rename.sh test1 test2 test3 test4 test5
# csh rename.sh
# ls
rename.sh tmp1 tmp2 tmp3 tmp4 tmp5
#

改良したプログラム(その1)

最初のプログラムはファイルの名前も、個数も決まっていた。
まず、名前を変えるファイルの個数を実行時に変更できるようにシェルスクリプトを 作り変えてみよう。 実行時のコマンド引数をシェルスクリプトの中で使うには argvという特別な変数(配列)を使う。

#!/bin/csh -f
set i = 1
while($i <= 5)
	mv $argv[1]$i $argv[2]$i
	@ i ++
end
# vi rename.sh    <- 上のプログラムをrename.shという名前で作る
# ls
rename.sh test1 test2 test3 test4 test5
# csh rename.sh
argv : Subscript out of range    <- エラーが出る
# ls
rename.sh test1 test2 test3 test4 test5    <- 変更無し
# csh rename.sh test tmp   <- 正しい使い方
# ls
rename.sh tmp1 tmp2 tmp3 tmp4 tmp5
#

改良したプログラム(その2)

その1のシェルスクリプトでは間違った使い方をするとエラーの表示が出て終っていた。
これでは使う人に不親切なので、間違った使い方をした時は 正しい使い方の簡単な説明が出るようにしよう。

#!/bin/csh -f
if($#argv != 2) then
	echo "Usage : rename.sh old-name new-name"
	exit 1
endif
set i = 1
while($i <= 5)
	mv $argv[1]$i $argv[2]$i
	@ i ++
end

ifの条件で $#argv != 2としているのは コマンド引数の個数が2以外の時は使い方が間違っているからである。 本当は、それらの引数の内容が正しいかどうかも調べるべきだが、 ここではそこまではしていない。

# vi rename.sh    <- 上のプログラムをrename.shという名前で作る
# ls
rename.sh test1 test2 test3 test4 test5
# csh rename.sh   <- 正しくない使い方をすると
Usage : rename.sh old-name new-name    <- 使い方の説明が出る
# csh rename.sh test tmp
# ls
rename.sh tmp1 tmp2 tmp3 tmp4 tmp5
#

改良したプログラム(その3)

これまでのプログラムでは名前を変えるファイルの個数は5個に固定されている。 これを実行時に変えることができるようにしよう。

#!/bin/csh -f
if($#argv != 3) then
	echo "Usage : rename.sh end-number old-name new-name"
	exit 1
endif
set i = 1
while($i <= $argv[1])
	mv $argv[2]$i $argv[3]$i
	@ i ++
end
# vi rename.sh    <- 上のプログラムをrename.shという名前で作る
# ls
rename.sh test1 test2 test3 test4 test5
# csh rename.sh   <- 正しくない使い方をすると
Usage : rename.sh end-number old-name new-name    <- 使い方の説明が出る
# csh rename.sh 4 test tmp     <- 4個名前を変える
# ls
rename.sh tmp1 tmp2 tmp3 tmp4 test5     <- tmp5は変わっていない
#

改良したプログラム(その4)

上のプログラムでは名前を変えるファイルの個数が1番目の引数として必要だったが、 今度はそれをオプションにして個数を指定してもしなくても どちらでも良いようにしよう。

#!/bin/csh -f
if($#argv != 2 || $#argv != 4) then
	echo "Usage : rename.sh [-e end-number] old-name new-name"
	exit 1
endif
set number = 5
set i = 1
while($i <= $#argv)
	switch($argv[$i])
	case -e :
		@ i ++
		set number = $argv[$i]
	breaksw
	default :
		set old = $argv[$i]
		@ i ++
		set new = $argv[$i]
	breaksw
	endsw
end
set i = 1
while($i <= $number)
	mv $old$i $new$i
	@ i ++
end
# vi rename.sh    <- 上のプログラムをrename.shという名前で作る
# ls
rename.sh test1 test2 test3 test4 test5
# csh rename.sh   <- 正しくない使い方をすると
Usage : rename.sh [-e end-number] old-name new-name    <- 使い方の説明が出る
# csh rename.sh -e 4 test tmp     <- 4個名前を変える
# ls
rename.sh tmp1 tmp2 tmp3 tmp4 test5     <- tmp5は変わっていない
#

最終的なプログラム

最後のバージョンとして、名前を変えるファイルの最初の番号と最後の番号を オプションで変えられるシェルスクリプトを作ろう。

#!/bin/csh -f
if($#argv < 2 || $#argv > 6) then
	echo "Usage : rename.sh [-s start-number] [-e end-number] old-name new-name"
	exit 1
endif
set start = 1
set end = 5
set i = 1
while($i <= $#argv)
	switch($argv[$i])
	case -s :
		@ i ++
		set start = $argv[$i]
	breaksw
	case -e :
		@ i ++
		set end = $argv[$i]
	breaksw
	default :
		set old = $argv[$i]
		@ i ++
		set new = $argv[$i]
	breaksw
	endsw
	@ i ++
end
set i = $start
while($i <= $end)
	mv $old$i $new$i
	@ i ++
end
# vi rename.sh    <- 上のプログラムをrename.shという名前で作る
# ls
rename.sh test1 test2 test3 test4 test5
# csh rename.sh   <- 正しくない使い方をすると
Usage : rename.sh [-s start-number] [-e end-number] old-name new-name    <- 使い方の説明が出る
# csh rename.sh -s 2 -e 4 test tmp    <- test[234]をtmp[234]に変える
# ls
rename.sh test1 tmp2 tmp3 tmp4 test5     <- test1, test5は変わっていない
#

まとめ

ここまででプログラムの開発は一応終るが、このシェルスクリプトは まだまだ改良の余地がある。 考えられる改良点として以下のものがあるだろう。

興味のある人はこのプログラムにこれらの機能を加えてみよう。

ここでは一つのシェルスクリプトに色々な機能をいれてゆく方針でプログラムを作っていったが、 必要な時に小さなシェルスクリプトを、その場で作ったり、書き換えて使うという方法もある。 例えば、その1で作ったプログラムのファイル名や数字をviでそのたびに書き換えて 使ってもかまわない。
いつも良く使うプログラムや、自分以外の人も使うは場合は複雑になっても汎用的に作っておき、 自分用のその場でしか使わないようなプログラムは、その時だけ使えるように小さなプログラムに しておけば良いだろう。

参考


Prev | Next
Home | Contents
abe@injapan.net