第 2 回 - フィルタ,シェルスクリプトの基礎(2)

[10/13, 2009 H.Aman]
67x27(1669bytes)   67x27(1669bytes) 【課題 3】

例題 3

コマンドライン引数として指定されたファイルについて, それが存在すればそのファイルの行数を表示し, 存在しない場合は「見つかりません」と表示するシェルスクリプト linecounter.sh を作りなさい.
ただし,行数のカウントには wc コマンドを利用すること.

解答例

     if [ -f $1 ]
     then
        wc -l $1 | cut -d " " -f 1
     else
        echo 存在しません
     fi

     ※計算機室で使用する wc コマンドのバージョンでは,
     行数を出力する際に複数のスペースが入ってしまい cut がうまくいかないようです.
        wc -l $1 | cut -d " " -f 1
     を次の二行に置き換えてみてください:
        count=$(wc -l $1)
        echo $count | cut -d " " -f 1
     

解説

前回説明したように, コマンドライン引数として与えられる ファイルの名前は $1 として参照できる.

ここでポイントなのは, このファイル($1)が現実に存在しているかどうかを判定し, その判定結果によって 次に実行すべきコマンドを使い分ける ということである.
ひたらく言えば,C 言語でいうところの if 文が必要になる.

bash でも if という構文は用意されており,以下のように記述する:


     if  条件
     then
        条件が成り立つ時に実行するコマンド列
     else
        条件が成り立たない時に実行するコマンド列
     fi

ただし,else とそれに続くコマンド列は省略できる.
if 文の終りが,fi (if を逆さまに書いている)であることに注意されたい. これは記述ミスではなく,こういう規則になっている.
また,then や else, fi の前後には必ず改行が必要である. どうしても改行したくない場合は,途中にセミコロン(;)を書けばよい.

条件部について,上の回答例では

     [ -f $1 ]
と書いている.
これは「ファイル $1 が存在する」という条件を意味している.
なお,[ や -f 等の前後には必ず空白文字(スペース)を入れること.
※これはややマニアックな話であるが,実は [ というのは一つのコマンドである (/usr/bin に置いてある). つまり,[ というコマンドを実行していて,そのオプションや引数として -f や $1, ] を書いている.

-f 以外にもオプションはいくつか用意されている. ファイル属性に関する使い方を以下に示す:
演算子 真の場合
 -d  file  file が存在し,かつディレクトリである
 -e  file  file が存在する
 -f  file  file が存在し,かつ通常ファイルである(ディレクトリや特殊ファイルではない)
 -r  file  file に read パーミッションがある
 -s  file  file が存在し,空ではない
 -w file  file に write パーミッションがある
 -x  file  file に execute パーミッションがある, ディレクトリの場合は search パーミッションがある
 -O file  file の所有者である.
 -G file  file のグループ ID が自分のものと一致する(複数のグループに属している場合はそのうちのどれかと一致する)
 file1 -nt  file2  file1 file2 よりも新しい
 file1 -ot  file2  file1 file2 よりも古い

もしも複数の条件を組み合わせたければ, && や || を使って

if [条件] && [条件]
then
     ....
などとする.

then 部で書いてある

     wc -l $1 | cut -d " " -f 1
と else 部で書いてある
     echo 存在しません
については,説明の必要はないと思われるので割愛する. (コマンド解説 wccut 参照)


(参考資料)

上表にはファイル属性に関する使い方を示した. その他の使い方についても以下に示しておく.

  • 文字列の比較
    演算子 次の場合に真
    str1 = str2 str1str2 が一致する
    str1 != str2 str1str2 が一致しない
    -n  str1 str1 が NULL ではない(長さが 0 より大きい)
    -z  str1 str1 が NULL である(長さが 0)

    例えば,

    	   if [ -z "$1" ]
    	   then
    	      echo "引数を指定してください"
    	      exit 1
    	   fi
    とすると第1引数が NULL であるときにエラーメッセージを出力して, 終了ステータス 1 で終了する(異常終了).
  • 整数による条件式

    条件式に < や > を使ってもそれは数値の大小を意味せず, 辞書式順序での比較になってしまう. 例えば,

    	   "6" > "57"
    は真となる. (これが数値ならば偽であることは明らか.)

    整数を比較する演算子を以下に紹介する:
     演算子  比較
     -lt  より小さい
     -le  以下
     -eq  等しい
     -ge  以上
     -gt  より大きい
     -ne  等しくない