第3章:シェル関数、組み込みコマンド

とりあえず、この第3章ではシェルスクリプトをさらに小さくした1つの固まりのコマンドだと言う程度の理解で十分で、詳しくは第9章でやるらしい。この章では、関数を使う上での注意点を見ていくようだ。

シェル関数

古くからある機能で、よく使われる機能で、一連のコマンドを単に処理するだけ。関数なので戻り値も設定できる。たとえば、ls -lと同じ動作をするシェル関数lslを作成する。

$ lsl(){
> ls -l
> }

動作状態による違い

定義した関数を実行すると、それはそのシェルの中で動作する。しかし、関数内でリダイレクトとかをさせると、サブシェルを作って動作する。
関数が、サブシェルで動作するかどうかによって、動作上の違いある。

ディレクト

関数終了時のディレクトリが変わる。
関数内でディレクトリを移動する動作を行ったとき、カレントシェルの場合にはその変更内容が残る。しかし、サブシェルの場合には、関数が終了すれば元のディレクトリに戻る。

変数

関数終了時に変数の内容が変わる。
関数内で変数に対して何か処理を行ったとき、カレントシェルの場合にはその変更内容が残る。しかし、サブシェルの場合には関数が終了すれば元の値に戻る。

exitコマンド

シェルが終了するかどうかが変わる。
関数内でexitコマンドを実行したとき、カレントシェルで実行している場合にはそのシェル自体が終了する。しかし、サブシェルの場合にはその関数が終了するだけ。

引数に関する注意

位置パラメータの$0の値が、シェルスクリプトとシェル関数では異なる。シェルスクリプトだと、$0はそのスクリプトの名前が格納されるが、シェル関数ではそのシェル関数を呼び出したシェルが格納される。
シェル関数の場合

$ display(){
> echo $0 $1 $2 $3
> }
$ display aaa bbb ccc
/bin/bash aaa bbb ccc

シェルスクリプトの場合

$ cat display
#! /bin/sh
echo $0 $1 $2 $3
$ ./display aaa bbb ccc 
./display aaa bbb ccc

変数に関して

シェルスクリプトを1つ作成すると、そのシェルスクリプトで使用させる変数や関数で使用される変数すべてが格納されるテーブルが1つ用意される。1つのシェルスクリプト内の複数の関数で、同じ変数名を使用しているとその変数は同じ変数として処理されてしまう。なので、変数を使用するときは異なる変数名を使うように気をつけるべし。

関数をカレントシェルで動作させる方法

通常、シェルスクリプトに書かれているコマンドは、そのシェルスクリプト内で動作する。決して、そのシェルスクリプトを実行したシェル上で動く訳ではない。しかし、下記のようにシェルスクリプトを実行するとカレントシェルでそのスクリプト内のコマンドを実行することが可能なる。

$ . シェルスクリプト

ちょっとわかりにくいのでソースを見ながら。まず、下記のようなシェルスクリプト書く。

$ cat aaa
#! /bin/sh
pse()
{
ps -ax | sort -bn
}

下記のようにこのスクリプトファイルを実行しても、pseが実行されるわけではありませんし、その後でpseと実行したって実行されるわけがない。

$ ./aaa
$ pse
pse; not found

しかし、先ほどのファイルを.(ドットコマンド)を使って実行するとpseをカレントシェルで実行可能になる。

$ . ./aaa
$ pse
ps -ax | sort -bnの実行結果が表示される

このようなシェルスクリプトは、現在のシェル環境を設定するためのシェルスクリプトとなっている。そこで、このようにシェル環境を設定するためのスクリプトファイルは、ファイルの最後に.shとつけ、さらに、直接実行されないように読み取りのみの権限にしておく。

組み込みコマンド

シェルにはじめから組み込まれているコマンドを組み込みコマンドと言う。個別のコマンドを個別に走らせるより組み込みコマンドを使用したほうが速さやリソース的に効率的らしい。詳しくは後の章で記載されているので、この章では簡単に見ていく。

ヌルコマンド(:)

何もしないが、必ずいつも成功する(真の結果を返す)コマンド。条件判定を必ず真にしたいときによく使用される。たとえば下記に示すようなwhileの場合。下記の例だとヌルコマンドでwhileの条件が必ず真にあるので無限ループになる。

while :
do
  if ....
  then
     break
  if
done
ドットコマンド(.)

新しくプロセスを作らずに、現行のシェルのプロセスを使って指定されたファイルを読み込み実行する。その結果、指定されたファイルに記載されている変数や関数が現行のシェルで使えるようになる。

breakコマンド

forやwhileのループから抜けるときに使うコマンド。いくつかのループをまとめて抜けるときには、breakの後に数字をパラメータとして渡すと抜けることができる。

cdコマンド

指定したディレクトリに移動するコマンド。パラメータがなければ、そのユーザのホームディレクトリに移動する。

continueコマンド

forやwhileでいったんループ内の処理を終えて、またループの最初の処理から行わせたいときに使用する。引数を渡すことで、ネストしている何番目のループに戻るかなんてことも可能。

echoコマンド

引数の部分を標準出力に表示するコマンド。特殊コードを出力させるときだけSystem V系BSD系で異なるらしい。詳しくは12章の汎用性でやる。

evalコマンド

1行に複数のコマンド実行が入っているとき、いっぺんに複数のコマンドを実行してくれる。

execコマンド

execコマンドは、引数のコマンドをカレントシェルのプロセスと置き換えて実行する。

exit

シェルを終了させたいときに使用する。引数を渡すとこのシェルの終了コードを設定することができ、その終了コードは$?に格納される。通常は、正常終了したときには0を格納する。

exportコマンド

パラーメタで指定された変数を、このタイミング以降で実行されたシェルやコマンドで使用できるようにする。通常、変数などは他のシェルからは見えないはずだが、それを見えるようにするのがexportコマンド。詳しくは第5章で。

pwdコマンド

現在いる完全パスを表示する。

readコマンド

キーボードからの入力をreadの後に指定されたものに格納する。readの後の複数の変数を用意すると、複数の入力値も格納できる。このとき、単語をスペースで区切るように使うスペースなどの区切り文字をIFS(Internal Field Separators)と言う。スペースのほかにタブ改行もIFSにあたる。詳しくは第4章、第8章で。

readonlyコマンド

指定された変数を読み出し専用にする。あんまし使用されないみたい。

returnコマンド

シェル関数から抜けるコマンド。returnの後に指定した番号がその関数の終了コードになる。

setコマンド

シェルのオプションをオンにしたりオフにしたりするコマンド。setで位置パラメータの値を設定すると、下記のように位置パラメータの値が全部クリアされるので注意。

$ cat aaa
#! /bin/sh
echo $0 $1 $2 $3 $4
set aa bb cc
echo $0 $1 $2 $3 $4
$ ./aaa 1 2 3 4 5
./aaa 1 2 3 4
./aaa aa bb cc

上記のようにsetで設定し直すことによって、$4の値がリセットされ出力されない。

shiftコマンド

このコマンドは位置パラメータを左にずらす。

testコマンド

ある条件を判定し、条件が真の場合は0、偽の場合は0以外の値を返す。条件として様々な判定をさせることができ、ファイルの読み取りチェックや文字列の長さチェックなどもテスト可能。何が判定できるかあまりに多いので、manを読んだり、サンプルソースで出てきたときにその都度勉強しなおすべし。

trapコマンド

シグナルを受け取ったときに、指定したアクションを実行することが可能。詳しくは第5章で。

typeコマンド

typeコマンドのパラメータにはコマンド名を指定する。パラメータで指定したコマンドの場所などを教えてくれる。サンプルを以下に示す。

$ type date
date is /bin/date
$
umaskコマンド

ファイルを生成するときに、読み書きなどどのモード(権限)で作るかを決定するコマンド。

unsetコマンド

指定した変数や関数を消去するコマンド。ただし、シェルが始めから持っている変数(PATHやIFS)などはunsetできない。

waitコマンド

引数に動作しているプログラムのプロセスIDを渡す。そのプログラムが終わるまで待つ。使い方としては、バックグラウンドで走っている処理が終わるのを待ち、終わったら処理を行いたい場合などに使用する。

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界