ソースコード・リテラシーのススメ

第21回 ソフトウェア・ツールズの活用[完結編]

この記事を読むのに必要な時間:およそ 5 分

完成版スクリプト

オプション解析機能を追加し,ヘルプメッセージの表示機能も関数化した完成版のコードはこうなりました。

リスト6 完成版のインストールスクリプト

  1  #!/bin/sh
  2  
  3  get_version() {
  4    local old_name=`cat /var/log/packages/$1 | grep "^PACKAGE NAME" | cut -f2 -d':' `
  5    local old_vers=`echo $old_name | cut -f2 -d'-'`
  6    echo  $old_vers
  7  }
  8  
  9  check_vers() {
 10    local old=$1
 11    local new=$2
 12  
 13    for i in 1 2 3 4 5; do
 14      t1=`echo $old | cut -f$i -d'.'`
 15      t2=`echo $new | cut -f$i -d'.'`
 16      if [ $t2 -gt $t1 ]; then
 17        return $t2
 18      fi
 19    done
 20    return 0
 21  }
 22  
 23  usage() {
 24    echo "usage: $0 [-f] [-h] package(s)"
 25    echo "    -f force install mode(without version check)"
 26    echo "    -h help(this message)"
 27    exit
 28  }
 29  
 30  for opt in  $* 
 31  do
 32    case $opt in
 33    -f)
 34      force_flag=1 ; shift ;;
 35    -h)
 36      usage ;;
 37    esac
 38  done
 39  
 40  if [ $# = 0 ]; then
 41    usage
 42  fi
 43  
 44  for tmppkg in $* ; do
 45    pkg=`basename $tmppkg`
 46    base=`echo $pkg | cut -f1 -d'-'`
 47    vers=`echo $pkg | cut -f2 -d'-'`
 48    chk=`ls /var/log/packages | grep "^$base$" `
 49    if [ "$chk.x" != ".x" ]; then
 50      if [ "$force_flag.x" != ".x" ]; then
 51        /sbin/removepkg $base
 52      else
 53        old_vers=`get_version $base`
 54        check_vers $old_vers $vers
 55        ver_test=$?
 56        if [ $ver_test != "0" ]; then
 57          /sbin/removepkg $base
 58        else
 59          echo "same or newer vesion($chk-$old_vers) has been installed."
 60          echo "installation stopped for $tmppkg"  
 61          continue
 62        fi
 63      fi
 64    fi
 65    /sbin/installpkg $tmppkg
 66  done

23から28行目が,以前はスクリプトの先頭部分に置いていたメッセージ表示機能を関数化したusageです。この関数は呼びだされると指定したメッセージを表示してスクリプトを終了(exit)させます。

30から38行目がオプションの解析部分で,オプションはパッケージ名よりも先に処理する必要があるためこの部分に置いています。

40から42行目は-fオプションを除いても引数(パッケージ名)が残っているかをチェックし,残っていなければコマンドの使い方が間違っているので,usageを呼び出してメッセージを出力,終了します。

パッケージをインストールする44行目からのループでは,50行目に$force_flagをチェックするif文を追加して,$force_flagに値が入っていれば,53行目からのバージョンチェックを行わず,古いパッケージをアンインストールするようにしました。

数字以外が含まれた際のバージョンチェックやパッケージごとの強制インストールの有無など,もう少しイジりたい気もしますが,あまり複雑にすると見直した時に自分でもわからなくなりがちなので(苦笑⁠⁠,今回のupdatepkgコマンドはこれくらいで完成ということにしておきましょう。

今回はシェルスクリプトを作っていく過程を順を追って紹介しました。たいていのソースコードは,今回の例のように,中心となる機能を作った上で付加的な機能やさまざまなチェック機能を追加しながら成長していきます。そのようなソースコードを読む際には,頭から丁寧に読んでいくよりも,まず全体をざっと流し読みして中心となる部分を見つけた上で,そこからどのような処理が呼び出されていくのかを追ってゆく方がわかりやすくなります。

本連載で紹介してきた文書の読み方同様,ソースコードもメリハリを付けて読むのがコツと言えるでしょう。

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたのが,いつの間にかミイラ取りがミイラになってOSSを仕事にするようになってしまいました。最近はスペシャリスト養成を目的とした専門職大学院で教壇に立ったりもしています。

URLhttp://www.linet.gr.jp/~kojima/Plamo/index.html