シェルスクリプトの制御構造

制御構造について

シェルでもC言語・MELのようなif, while, switchなどの制御構造が使用できる。
また、MELにおけるfor( in )のようなforeachもある。

ifの使用方法

以下のようにthenendif がC言語・MELの { と } に対応する。

  1. 条件が成り立てばコマンドの部分を実行。
    if(条件) then
        コマンド
           .
           .
    endif
    
  2. 条件が成り立てばコマンド1、成り立たなければ、コマンド2の部分を実行。
    if(条件) then
        コマンド1
           .
           .
    else
        コマンド2
           .
           .
    endif
    
  3. 条件1が成り立てばコマンド1、成り立たなければ、条件2を調べて成り立てばコマンド2の部分を実行。
    以下、同様に else if の条件を調べて成り立っていればその下のコマンドを実行。
    すべての条件が成り立たなければコマンドnを実行。
    if(条件1) then
        コマンド1
           .
           .
    else if(条件2) then
        コマンド2
           .
           .
    else
        コマンドn
    endif
    
  4. コマンドが1つだけの場合は thenendif が省略できる。
    if(条件) コマンド

ifの使用例1

まず、コマンドラインから if を色々と試してみる。
ここでは実行するコマンドの例として echo コマンドを使用しているが、もちろんこのコマンド以外のコマンドも使用できる。

% set x = 3
% if($x > 1) echo test        ← 条件が成り立っているので
test                          ← コマンド(echo test)が実行される
% if($x + 2 > 1) echo test    ← 条件に数式を使う(条件が成り立っている)
test                          ← コマンド(echo test)が実行される
% set y = 2.5
% if($y > 1.0) echo test      ← 条件に実数が使われていると
if: Badly formed number.      ← エラーになる
% set z = aaa
% if($z == "aaa") echo test   ← 文字列同士を比べる
test
% ls
test1.ma test2.ma
% set f = test1.ma
% if(-f $f) echo $f exist     ← test1.maが存在するかどうか調べてコマンドを実行
test1.ma exist                           ← コマンド(echo $f exist)が実行される
% set files = ( `ls *.mb` )
% if($#files > 0) echo test   ← *.mbファイルが1つ以上あれば echo コマンドを実行(ないので実行されない)
% cat test1.ma | wc -l        ← test1.maの行数を調べるコマンド
238                           ← test1.maの行数は238
% if(`cat test1.ma | wc -l` > 200) echo test    ← test1.maの行数が200以上であれば echo コマンドを実行
test                          ← コマンド(echo test)が実行される

ifの使用例2

次に、ifを使ってtest.maというデータファイルが存在していればMAYAでレンダリングするシェルスクリプトを作って実行してみよう。
レンダリングにはRenderコマンドを使用している。

  1. viで以下のシェルスクリプト(render.sh)を作る。
    set f = test.ma
    if(-f $f) then
    	Render -rd . $f
    endif
    
  2. 上のシェルスクリプトを実行すると以下のようになる。
    % ls
    render.sh test.ma
    % csh render.sh
    .......    ← test.maをレンダリング
    % ls
    render.sh test.1.iff test.2.iff test.3.iff test.ma
    % fcheck -n 1 3 1 test.@.iff    ← アニメーションのチェック
    %
    

while

シェルでもC言語のようなwhile文が使用できる。
シェルで使用するwhile文の形式は次の通り。

while(条件)
    コマンド
end

C言語・MELの { と } は無くて、そのかわり end が最期につく。
条件は if で紹介した条件と同じである。

whileの使用例

MAYAでレンダリングされた画像ファイル名を変換するシェルスクリプトを作ってみよう。
vi で以下のシェルスクリプトを rename1.sh という名前を作る。

set i = 1
while($i <= 3)
	mv test.$i.iff kadai.$i.iff
	@ i ++
end
上のシェルスクリプトを実行すると以下のようになる。

% ls
rename1.sh test.1.iff test.2.iff test.3.iff
% csh rename1.sh
% ls
rename1.sh kadai.1.iff kadai.2.iff kadai.3.iff
%

シェルスクリプトの解説

set i = 1
変数 $i に1を代入する。
while($i <= 3)
変数 $i が3になるまでループする。
mv test.$i.iff kadai.$i.iff
ファイル名 test.$i.iff を kadai.$i.iff に変更。
@ i ++
変数 $i をインクリメントする。 ($i に1を加える)
end
while の終り。

foreach

シェルではC言語には存在しない、foreach というループが使用できる。
MELでは似たものとして for( in ) がある。
特定の名前のファイルなどに対してコマンドを実行する場合などに便利である。
foreach ではリストの中の要素を一つづつ変数に代入してコマンドを実行する。
リストの部分にはファイル名、変数(配列)やコマンドの結果(コマンド置換)などが使用できる。

foreach 変数 ( リスト )
    コマンド
end

foreachの使用例

下の例ではカレントディレクトリにあるJPEGフォーマットの画像ファイルをGIFフォーマットに変換している。 (フォーマット変換には convert コマンドを使用している。)

  1. 以下のシェルスクリプトをviによって convert.sh という名前で作る。
    foreach f (*.jpg)
    	convert $f $f:r.gif
    end
    
    $f:r はファイル名からピリオド以下の部分を取り去ったものになる。
    $f の中身が tmp.jpg だとすると $f:r は tmp になる。
    ($f:r.gif は tmp.gif になる)
    この :r のことを変数の修飾といい、:r の他に以下のものがある。
    :h
    パス名を取り出す。
    % set nn = /aaa/bbb.ccc
    % set n1 = $nn:h
    % echo $n1
    /aaa
    
    :e
    拡張子を取り出す。
    % set nn = /aaa/bbb.ccc
    % set n2 = $nn:e
    % echo $n2
    ccc
    
    :t
    ファイル名と拡張子を取り出す。
    % set nn = /aaa/bbb.ccc
    % set n3 = $nn:t
    % echo $n3
    bbb.ccc
    
  2. 以下のように実行してみる。
    % ls
    convert.sh kadai.jpg test.jpg tmp.jpg
    % csh convert.sh
    % ls
    convert.sh kadai.gif kadai.jpg test.gif test.jpg tmp.gif tmp.jpg
    %
    
    上のforeachでは以下の様に処理が進む。
    1. foreach f (*.jpg)foreach f (kadai.jpg test.jpg tmp.jpg) と展開される。
    2. foreach によって set f = kadai.jpg が実行される。
    3. convert $f $f:r.gif によって convert kadai.jpg kadai.gif が実行される。
    4. foreach によって set f = test.jgp が実行される。
    5. convert $f $f:r.gif によって convert test.jgp test.gif が実行される。
    6. foreach によって set f = tmp.jpg が実行される。
    7. convert $f $f:r.gif によって convert tmp.jpg tmp.gif が実行される。

switch

シェルのswitch文はC言語のswitchに似ているが、もう少し柔軟な使い方ができる。
シェルで使用するswitch文の形式は以下の通り。

switch(変数)
	case 値1 :
	    コマンド1
	    breaksw
	case 値2 :
	    コマンド2
	    breaksw
	    .
	    .
	default :
	    コマンド
endsw

C言語の ように{ と } は無くて、そのかわり endsw が最期につく。
値1、値2...の部分には数値・文字列どちらでも使用できて、正規表現も使うことができる。
例えば、値1または値2の部分が *.c であればファイル名の最期の2文字が .c であるようなファイル(C言語プログラム)になり、*.m[ab] であると最期の3文字が .ma または .mb であるようなファイル名(MAYAデータファイル)になる。
実行される順番は以下の通り。

  1. 変数が値1にマッチするかどうか調べる。
  2. マッチすれば、コマンド1を実行して終り。
  3. マッチしなければ、次の値2にマッチするかどうか調べる。
  4. マッチすれば、コマンド2を実行して終り。
  5. 以下、同様に case の値とマッチしているかどうか調べていってマッチしている部分のコマンドを実行して終る。
  6. 全ての case の値にマッチしなければ default のコマンドを実行する。
    default は省略可能。

switchの使用例

画像ファイルの表示とMAYAのレンダリングを一つのプログラムで実行できるシェルスクリプトを作ってみよう。
以下のシェルスクリプトをviによってdo1.shというファイル名前で作る。

switch($argv[1])
	case *.iff :
		fcheck $argv[1]
		breaksw
	case *.ma :
		Render $argv[1]
		breaksw
endsw
上のシェルスクリプトを実行すると以下のようになる。
(サンプルデータkadai.maをホームディレクトリの下のunix2にダウンロード。)

% csh do1.sh kadai.ma
...   ← Render kadai.ma を実行
% csh do1.sh test.iff
...   ← fcheck test.iff を実行
% csh do1.sh kadai.jpg
%   ← 何も実行しない

練習課題

参考


Prev
Home | Contents
abe@injapan.net