UNIXの基本操作

シェルスクリプト

UNIXではUNIXのコマンドやシェルの組み込みコマンドを用いてプログラムし、ユーザ が独自の便利な機能を作ることができる。これをシェルスクリプトあるいはシェル プログラムと呼ぶ。

シェルスクリプトの書き方

 シェルスクリプトの簡単な例を示す。


  { kipces3 } 11%  cat aisatu 
    #! /bin/csh
    # Example of csh script
    echo "Good morning!"
  { kipces3 } 12% 

図5.52 シェルスクリプトの簡単な例
  シェルスクリプトの1行目は必ず例のように#!の次に使用するシェルを指定する。 2行目の#から始める行はコメントでシェルスクリプトのメモを書く。これは1行目 以外なら自由でなくても良い。実は1行目に#を書くと csh がログインシェルの場合 は csh が # でなければ sh(Bシェル、あるいは標準シェルとも呼ばれる)が選択される。 図5.52におけるシェルの指定方法は sh,csh 以外にも UNIX には沢山のシェルが存在する ので任意のシェルを選択するのに使う。3行目は本体で echo コマンドを使い、 ディスプレイに Good morning! と表示をする。表示をする文字列は ”で囲んで書く。 作成したシェルスクリプトを実行するためには次節で述べるようにファイルの属性を 実行可能に変更する必要がある。

シェルスクリプトの実行方法

図5.53の1行目に示すように chmod コマンドを使ってファイルを実行可能とする。 ここで、 u+x とあるのは所有者(user)に実行許可(x)を与える(+)という意味 である(実行許可をなくす場合は chmod u-x aisatuとすればよい。)。 2行目に示すように ls コマンドを実行して,ファイルの詳細情報を見てみよう。 3行目の4文字目の x がファイルの所有者がそのファイルの内容を実行できるよう に変更されたことを意味する。


  { kipces3 } 13%  chmod u+x aisatu 
  { kipces3 } 14%  ls -l aisatu 
    -rwxr--r-- 1 matumoto 5 Sep  0  14:00 aisatu
  { kipces3 } 15%  aisatu
    Good morning! 
  { kipces3 } 16% 

図5.53 シェルスクリプトの実行方法
  この例のシェルスクリプトはディスプレイに文字を出力するが、キーボードから 入力することもできる。キーボードからの入力はシェルスクリプト内で $< と 書く事により行える。例を示す。


  { kipces3 } 17%  cat namedisp 
    #! /bin/csh 
    # Example of csh script
    echo -n "Input your first name : "  
    set name=$ <
    echo "Hi, name$"  
  { kipces3 } 18% 

図5.54 キーボード入力のシェルスクリプト例
  4行目の echo コマンドで -n オプションを付けて実行することにより、通常の実行では 文字列を出力後に改行してしまうのを抑制している。5行目でキーボードからの入力を 変数nameに代入している。

演習課題

  1. 例に示した aisatu をエディタvi で作成し、実行してみよ。
  2. 例に示したnamedisp をエディタvi で作成し、実行してみよ。
  3. namedisp をフルネームで表示するように変更せよ。。

シェルスクリプトの基礎

シェルスクリプトはこれまでに説明した形式でファイルに次々とコマンドを何行にも 渡って書くことにより、多くの機能を実現できる。しかし。これでは実現できる機能 は限られてしまう。そこで条件、判定、繰り返し等の機能を説明する。

条件、判定には if 文があり、以下のように記述する。


  if (条件式) then
      コマンド1
      コマンド2
        :
    endif

    if (条件式) then
      コマンド1
    else
      コマンド2
    endif

    if (条件式1) then
      コマンド1
      else if(条件式2) then
         コマンド2
           :
         else
    コマンドN
    endif

if 文の例を紹介する前に変数やコマンドの引き数について説明する。まず最初に変数 であるがこれにはユーザが定義する変数とシェルが起動されたときに設定される シェル変数の2種類がある。賢明な諸君は既に .cshrc というファイルの説明を思い 出していると思うが 「set path=(. /usr/ucb /bin .... ) とあるのはユーザ の入力したコマンドがどこにあるか探す際の順番を設定している。」とあるのはシェル 変数に set コマンドで値を設定していたのである(これからわかるように .login や .cshrc ファイルはシェルスクリプトの1種である)。この値は設定したシェルを使って いる限りシェルスクリプトの中で使用できる。値の設定の方法は


  set 変数=値
    set 変数=(値1 値2 値3 ・・・ )

この値を参照する場合は$変数と書けば変数の値を参照できる。次に引き数について説明する。 シェルスクリプトで必要な機能を持ったコマンドを作る際にファイル名などを引き数として 取り込むと便利な場合がある。Cシェルではシェルスクリプトが実行されると、コマンド自身は $0 に入り、引き数はシェル変数に順番に入る。コマンド名とその引き数を表示(エコーバック するという)するシェルプログラムは図5.55のようになる。


  { kipces3 } 1%  cat disp 
    #! /bin/csh 
    echo $0
    echo $argv[1]
    echo $argv[2]
    echo $#argev     
  { kipces3 } 2% disp arg1 arg1
    disp 
    arg1
    arg2 
    2           
{ kipces3 } 3%

図5.55 シェルスクリプトdisp
  シェルスクリプト disp の5行目の echo $#argev は引き数の数を表示している。 これで変数の引き数が理解できたので if コマンドを使ったシェルスクリプトの例を紹介する。


  { kipces3 } 1%  cat filedisp 
    #! /bin/csh 
    if ( $#argv == 0 ) then  
         echo You must type: "$0 filename" 
         exit
    else  
         cat $argv[1] 
    endif 
  { kipces3 } 2%  filedisp 
    You must type: filedisp filename
    { kipces3 } 3%

図5.56 if thenを使ったシェルスクリプトの例
  ここで新しいコマンド exitが使われているがこれはシェルスクリプトを 終了するときに使う。ここではコマンドの引き数が0(1個もない)の時は "You must type: filedisp filename" と表示し、スクリプトを終了するのに使われて いる。()内の条件式は論理和、論理積、否定が使える


  論理和 条件式1 || 条件式2
    論理積 条件式1 && 条件式2
    否定    ! 条件式

シェルスクリプト filedisp の2行目の $#argv == 0 は引き数の数が0と等しいか? と判定をしている。条件式で文字列や数字(整数値のみ)の大小を判断する条件式 には以下のようなものがある(条件式は真の時は1、偽の時は0を返す)。


    文字列1==文字列2 :等しい?
    文字列1|=文字列2 :等しくない?
    文字列1=~ パターン  :パターンと一致?
    文字列1!~ パターン  :パターンと等しくない?
    数字1>数字2    :数字1は数字2より大きいか?
    数字1>=数字2   :数字1は数字2以上か?
    数字1<数字2    :数字1は数字2より小さいか?
    数字1>=数字2   :数字1は数字2以下?

そのほかにファイルに関する条件式があり、シェルスクリプトを作るときには非常に 有用である。


    -e ファイル名   :ファイル名で指定したファイルが存在しているか?
    (UNIXでは通常のファイルの他に,ディレクトリや特殊ファイルもある。)
    -f ファイル名   :ファイル名で指定した通常のファイルが存在しているか?
    (普通のファイル,いわゆるplain fileであるかの判定をする。)
    -d ディレクトリ名 :ディレクトリ名で指定したディレクトリが存在しているか?
    -z ファイル名   :ファイル名で指定したファイルは空か?
    -r ファイル名   :ファイル名で指定したファイルは読み込みが可能か?
    -w ファイル名   :ファイル名で指定したファイルは書き込みが可能か?
    -x ファイル名   :ファイル名で指定したファイルは実行可能か?

シェルスクリプトで繰り返しを行う組み込みコマンドには foreach や while を使う。 最初にforeach組み込みコマンドを説明する。書き方は以下のように行う。


    foreach 変数名(引き数1 引き数2 ・・・・ 引き数N)
        コマンド1
        コマンド2
          :
        コマンドN
    end

指定されたディレクトリーにあるファイルのコピーをファイル名 .bak と言う名前で作る シェルスクリプトの例を示す。(図5.57)


  { kipces3 } 1%  cat dispdir 
    #! /bin/csh 
    if ( $#argv == 0 ) then  
         echo You must type: "$0 directry_name" 
         exit
    else  
         set dir = $argv[1]
         cd $dir
         foreach file ( * )
         if (-f $file) $file > $file.bak
         end
    endif 
  { kipces3 } 2%  dispdir test 
  { kipces3 } 3%  cd test 
  { kipces3 } 4%  ls 
    test1 test1.bak test2 test2.bak test3 test3.bak 

図5.57 foreachを使ったシェルスクリプトの例
  ここで foreach の中で使用している fileコ マンドは引き数で指定されるファイルの型を 調べるコマンドで、この例では * によって指定されたディレクトリの全てのファイルを 調べている。 次に、while について述べる。while の書き方は以下のように行う。


  while (条件式) 
       コマンド1
      コマンド2
      コマンド3
        :
    end   

  括弧内の条件式はこれまでに説明したものが使え、条件式を判断し、満足している間は end までのコマンドを繰り返す。条件式を判断した結果、最初から満足しない場合は コマンドを実行せずに end 以下のコマンドに移る。 while と同時に使うと便利なコマンド に shift コマンドがある。これは引き数で指定した変数をシフト、つまり順番に参照できる。 while とシフトを使った例を示す。(図5.58)


  { kipces3 } 1%  cat suampro 
    #! /bin/csh 
    @ sum = 0     
    while ($#argv !=0) 
    @ sum = $sum + $argv[1]
    shift argv 
    end
    echo "SUM=$sum" 

図5.58 whileとshiftを使ったシェルスクリプトの例
  この例は引き数で指定された数字の和を求めるシェルスクリプトで、csh ではこのよう に算術演算も可能である。3行目は和を格納する変数 sum の初期化で,文字でなく10進数 を変数に格納する場合は変数の前に1つ空白を置いて@を記述する.4行目では引数の数を 判定し、0になるまで while以下のコマンドを実行する。5行目は和の算術演算、6行目は引き数の シフトを行っている(shift により argv の引き数の番号が1つ増加し、残りの引き数の数が 1つ減少する)。

最後に異なるパターンの処理を行うのに便利な switch と case コマンドを紹介する。書き方は 以下の通り。


  switch (文字列) 
       case パターン1
           コマンド
           :
            breaksw 
       case パターン1
           コマンド
           :
            breaksw 
       case パターン1
           コマンド
           :
            breaksw 
    default:
           コマンド
           :
            breaksw 
    endswitch  

  例を示す。(図5.59) この例のシェルスクリプトは "partcat オプション ファイル名" と入力 すると指定されたオプション、例えば -top が指定された場合は head コマンドを使って 指定されたファイルの先頭10行を、-bottom が指定された場合は tail コマンドを 使ってファイルの最後から10行を、そして -all が指定された場合は cat コマンドで ファイル全体を表示する物である。


  { kipces3 } 1%  cat partcat 
    #! /bin/csh 
    set file = $argv[2]      
    switch ($argv[1])  
            case -top
            head $file
             breaksw 
        case -bottom 
            tail $file
            breaksw 
        case -all 
            cat  $file 
            breaksw 
        default: 
            echo "ERROR"
    endsw                    

図5.59 switchとcaseを使ったシェルスクリプトの例
  演習課題

  1. 図5.55のdispを入力し、動作を確かめた後に、コマンド名や引数を一行の中に表示し、 引数の数を次行に表示する等変更せよ。
  2. 図5.56のシェルスクリプトfiledispを引数が1つ以外の場合にエラー表示するように変更せよ。
  3. 2のシェルスクリプトを引数がディレクトリの場合にエラー表示するように変更せよ。
  4. 図5.57のdispdirにディレクトリがあったらその旨を表示する機能を追加せよ。
  5. 図5.58のsumpro をsiftコマンドを使わない形で書き直せ。
  6. 図5.59のpartcatをこれまでの知識を用いて、各自の思うように改良せよ。
  7. 自習で作成したシェルスクリプトなどで必要な物はフロッピーディスクにコピーし、それ 以外は消去し、使用前と同じ状態にせよ。


CONTENTS


BACK