シェルスクリプト作成のテクニック Part 2

Hiroshi Tomioka
(2008年9月 9日 12:00) |

※このエントリーは、developerWorks : AIX and UNIXの「Speaking UNIX: More shell scripting techniques」を翻訳したエントリーのPart 2です。

【訳注】 「シェルスクリプト作成のテクニック Part 1」の続きのエントリーです。

スクリプトは柔軟に

初心者がプログラミングする際に直面する別の問題が、プログラムやシェルスクリプトの中に静的な値をハードコードしてしまうことです。これはスクリプトの柔軟性を損なってしまい、要するに悪いプログラミングだとみなされます。スクリプトを動かすためにシステム管理者や開発者がその都度スクリプトを修正するのではなく、他の値を与えた場合にもスクリプトが動くように、変数と引数をスクリプトや関数に追加しておきましょう。

それでは例題です。Listing 3は柔軟性のない品質の低いスクリプトの例です。

Listing 3: 柔軟性のないスクリプトの例

#!/bin/bash

if [[ -f /home/cormany/FileA ]]
then
  echo "Found file '/home/cormany/FileA'"
elif [[ -f /home/cormany/DirA/FileA ]]
then
  echo "Found file '/home/cormany/DirA/FileA'"
else
  echo "Unable to find file FileA"
fi

このスクリプトは一つのファイルを2つの場所から探すことしか出来ない用途の限定的なスクリプトです。

もっと考え方を広げてみましょう。Listing 4では同じような動作をしますが、どんなファイルでも、どんな場所からでも探すことが出来るようにしてみましょう。

Listing 4: より柔軟性の増したスクリプト

#!/bin/bash

exit_msg() {
  [[ $# -gt 1 ]] && echo "${0##*/} (${1}) - ${2}"
  exit ${1:-0}
}

[[ $# -lt 2 ]] && exit_msg 1 "Usage: ${0##*/}  "

_FNAME="${1}"
_DNAME="${2}"

[[ ! -d "${_DNAME}" ]] && exit_msg 2 "Unable to read or find directory '${_DNAME}'"

if [[ -f "${_DNAME}/${_FNAME}" ]]
then
  exit_msg 0 "Found file '${_DNAME}/${_FNAME}'"
else
  exit_msg 3 "Unable to find file '${_DNAME}/${_FNAME}'"
fi

この例ではより柔軟になりました。ユーザーは探して欲しいファイルと探したい場所を入力できるようになりました。

オプションを追加する

シェルスクリプトを作成する際、ある人が「これがあれば便利だよね!」とか「これもやってくれるなんて凄いよね!」と言っている一方で、他の人はそんなものはいらないと思っていたり、そんな余計な動作はして欲しくないと思っていたりします。人々は選択出来ることを喜びます。それならば彼らにオプションを与えましょう。ビルトインされているシェルコマンドのgetoptはこの役割をしてくれます。

Listing 5は、AIXでgetoptがどのように動作するかを説明した例です。

Listing 5: getoptの例

#!/usr/bin/ksh

_ARGS=`getopt -o x --long xxxxx -n ${0##*/} -- "$@"`
while [[ $# -gt 0 ]]
do
  case "${1}" in
    -x|--xxxxx)  echo "Arg x hit!"; shift;;
            --)  shift; break;;
             *)  echo "Invalid Option: ${1}"; break;;
  esac
done

getoptを含むスクリプト(ここでは仮にopttestとします)を実行する際、-xまたは--xxxxxという有効な引数を与えると、getoptはswitch判定を行い、case switchの中のコードを実行します。

# ./opttest -x
Arg x hit!

今度は無効なswitchオプションを与えて実行してみます。

# ./opttest -a
Invalid Option: -a

【訳注】 「シェルスクリプト作成のテクニック Part 3」に続きます。