name()
{
command
...
}通常のコマンドを実行するように、nameと打てば、実行できるようになります。
ls -lと同じ処理を行うlalという関数を作成します。
lal() {
> ls -l
> }touch file1
lal
total 0
-rw-r--r-- 1 jun staff 0 2 23 12:55 file1現在のシェルを終わらせるまでは、いつでもlal関数を実行可能です。
関数ではその関数の戻り費を自分で設定できます。 returnコマンドを任意の位置に書き、そこで戻り値を設定できます。
return コマンドを明示的に書いていない場合の戻り値は、関数内の最後に実行された コマンドの実行終了ステータスになります。
定義した関数を実行するとき、通常そのシェルの中で動作し、別のサブシェルを作りません。
ただし、関数内で標準入出力ををリダイレクトするような場合サブシェルを作って動作します。
関数がサブシェルを作って動作するかどうかによって、ちょっとした動作上の違いが起こります。
関数内でディレクトリを移動する操作を行ったとき、カレントシェルで実行している場合には、 関数の終了時にディレクトリはそれにつられて移動しています。 一方サブシェル内で実行している場合には、関数の終了後、元のディレクトリに戻ります。
関数内でなにか変数に対して処理を行ったとき、カレントシェルの場合にはその変更内容が残ります。 サブシェルの場合には関数が終了すれば元の値に戻ります。
関数内でexitコマンドを実行したとき、カレントシェルで実行している関数の場合には、 関数はもちろんそのシェル自体が終了します。 サブシェルで実行している場合には、その関数が終了するだけです。
lal関数に位置パラメタの指定ができるようにしてみましょう。
lal(){
> ls -l $*
> }lal file*
-rw-r--r-- 1 jun staff 0 2 23 12:55 file1postdisplay(){
> echo $0 $2 $3 $4
> }
postdisplay aa bb cc dd # postdisplayを引数付きで実行
postdisplay bb cc dd # $2 $3 $4が出力される。$0は関数名。位置パラメタを使用する関数を利用する場合には、実行する前に シェルスクリプトに引数として指定されたパラメタを何らかの形で保存しておく方が良い。
#!/bin/sh
POS_PARAM="$@" # POS_PARAM変数に引数のリストを代入しておく。
some_function(){
set ... # setコマンドで位置パラメタを設定し直したり
shift # shiftコマンドでずらしたりすると、
}
some_function # 関数を利用した後では、位置パラメタもずれてしまう。
set "$POS_PARAM" # よって代入していた変数の値に戻して再利用する。シェルスクリプトを1つ作ると、それで利用する変数を収めるテーブルが、1個用意されます。 その中に、シェルスクリプトで使う変数も、関数で使う変数も全て収められます。 このため、1つのシェルスクリプトで複数の関数を利用している場合など、 ある関数の中で使用する変数を使いたい場合には、他の関数で使用する変数の名前とが同じであれば それは同じ変数として処理します。 つまり関数の中でだけ利用する変数を使いたい場合には、他の関数やそれを呼んだシェルスクリプトでは決して 使わないような特殊な名前を使うようにするべきです。
普通、シェルスクリプトに含まれるコマンドはそのシェルスクリプト内で動作し、 シェルスクリプトを起動したシェル上で動くわけではありません。
ところが、次のようにすれば、シェルスクリプトをカレントシェルで実行させることも可能です。
. script_file関数も同じで、シェルスクリプト内で定義した関数は現在のシェルでは使えず、 そのシェルスクリプトの中でしか有効ではありません。 ドットコマンドを使って実行することにより、中に含まれる関数を現在のシェルが認識し利用できるようになります。
vim script#!/bin/sh
pse()
{
ps -ax | sort -bn
}上記のシェルスクリプトをドットコマンドを使っカレントシェルで実行できるようになります。
. ./script
pse
......いつも真の結果を返すコマンドです。 実行終了ステータスで0を返します。
無限ループを作るのに利用できます。
while :
do
if ...
then
break
fi
doneまた、if文の分岐内で何もしない場合の記述にも利用できます。
if comamnd-list
then
:
else
command
fithenの後には、何か1つはコマンドが必要なためです。
ヌルコマンドを利用して、空のファイルを作ることもできます。
: > filename. fileという形で使います。
新しくプロセスを作らずに現行のシェルのプロセスを使って指定されたファイルを 読み込み実行します。
その結果、指定されたファイルで記述されている変数や関数が、 現行のシェルで有効に使えるようになります。
forやwhileのループから抜け出る時に使用するコマンドです。
デフォルトでは1個のループを抜けます。
cd directoryで指定したディレクトリに移動します。
forやwhileのループ内で、次のループ処理に移行したい場合に利用します。
echo parameter引数の部分を標準出力に表示するコマンドです。
複数の変換処理を1度にやってしまいたい時に利用します。
VAR1=value
VAR2=VAR1
eval echo $"$VAR2"
valueevalコマンドは、変数の置き換えやコマンドの変換、ワイルドカードの展開などが複雑に 絡んでいる時に1行のコマンドでいっぺんに展開させてしまうものです。
また、evalコマンドはあるコマンドの結果が「何かを実行させるコマンドの形式をとって」返されたとき、 それをそのまま実行させるというような場合にも使用します。
eval `echo $"$VAR2"`
zsh: command not found: value展開した結果のvalueという文字列をそのままコマンドとして実行させようとしています。
exec commandexecコマンドは、新しくプロセスを作らず現行のカレントシェルのプロセスと置き換えて、 引数のコマンドを実行させます。 このコマンドを実行したら、もう元のシェルに戻ることはありません。
#!/bin/sh
exec ls -l
echo abc./exec
total 16
-rwxr-xr-x 1 jun staff 30 2 25 06:28 exec
-rw-r--r-- 1 jun staff 0 2 24 18:17 hello
-rw-r--r-- 1 jun staff 6 2 24 18:15 hello.txt
-rw-r--r-- 1 jun staff 0 2 24 18:17 hello2exitコマンドはシェルを終了するときに使います。 シェルスクリプトの中で書いた場合にはそのシェルスクリプトを終了します。 シェルスクリプト実行中に何らかのエラーが発生した時、その時点で実行をやめたい場合 にこのコマンドを使います。
exit numberexport namenameで指定した変数を、これ以降に起動した他のコマンドやシェルからも利用できるようになります。
カレントディレクトリの絶対パスを表示します。
read variableキーボードからの入力をvariableという変数にセットします。
#!/bin/sh
echo "enter yes or no --> \c"
read ANSWER
echo $ANSWER./answer
enter yes or no --> yes
yesyesという文字をタイプしたので、ANSWERという変数にはyesという文字が代入されます。
readonly name...nameで指定された変数を書き換え不可にします。
シェルスクリプト中にはあまり使われず、対話的処理の中で、誤って値を変えてしまいたくない 変数に設定します。
return exitstatusシェル関数から抜けるコマンドです。exitstatusに指定した番号がその関数の終了コードになります。
指定されなかった場合には、コマンドの実行終了コードが返ります。
sh
sh-3.2$ echo abc
abc
sh-3.2$ set -v
sh-3.2$ echo abc
echo abc
abc
sh-3.2$ set +v
set +v
sh-3.2$ echo abc
abcsetコマンドはシェルのオプションをオンにしたりオフにしたりします。
位置パラメタの値を左にずらします。
shiftというファイル名で実行した場合の例です。
cat shift
#!/bin/sh
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
shift
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9shift aa bb cc dd ee ff gg hh ii
☁ 3 ./shift aa bb cc dd ee ff gg hh ii
./shift aa bb cc dd ee ff gg hh ii
./shift bb cc dd ee ff gg hh ii引数に数値を指定するとその数だけshiftします。
testコマンドは、ある条件を判定し、正しいか正しくないかによって真(0)偽(0以外)の値を返します。
| オプション | 説明 |
|---|---|
| -r file | fileが読み取り可なら真 |
| -w file | fileが書き込み可なら真 |
| -x file | fileが実行可なら真 |
| -f file | fileが普通のファイルなら真 |
| -d file | fileがディレクトリなら真 |
| -s file | fileが0より大きいサイズなら真 |
| オプション | 説明 |
|---|---|
| -z string | stringの長さが0なら真 |
| -n string | stringの長さが0より大きいなら真 |
| string | stringがヌルでなければ真 |
| str1 = str2 | str1とstr2が同じなら真 |
| str1 != str2 | str1とstr2が同じでないなら真 |
| オプション | 説明 |
|---|---|
| intl -eq int2 | int1とint2が等しいなら真 |
| intl -ne int2 | int1とint2が等しくないなら真 |
| int1 -lt int2 | int1がint2より小さいなら真 |
| int1 -le int2 | int1がint2以下なら真 |
| int1 -gt int2 | int1がint2より大きいなら真 |
| int1 -ge int2 | int1がint2以上なら真 |
| オプション | 説明 |
|---|---|
| ! | NOTの意味。この直後の判定が偽ならば真 |
| -a | AND。前後の判定が真なら真 |
| -o | OR。前後の判定のどちらかが真なら真 |
| (expr) | グルーピング。判定の優先順を決める |
[ -r file -a -w file -a ! -x file ]
# 読み書き可能で、実行不可のfileなら真[ -d directory -a -x directory ]
# directoryがディレクトリで、移動可能なら真[ $NUM1 -gt $NUM2 ]
# $NUM1が$NUM2より大きい場合は真[ "$STRING" != "" ]
# $STRINGに何らかの文字が代入されていれば真[ $NUM1 -lt $NUM2 -o $NUM1 -gt $NUM3 -a $NUM2 -le $NUM3 ]
# $NUM1が$NUM2より小さいか、または、$NUM1が$NUM3より大きく$NUM2が$NUM3以下の場合真丸括弧はシェルの特殊文字であるため、クォートしておく必要があります。
ll # 権限の確認
-rwxrwxrwx 1 jun staff 108 2 25 21:08 testfile
---------- 1 jun staff 0 2 25 21:13 xxx
cat testfile # testfileの中身を確認
#!/bin/sh
if [ ! \( -r xxx -a -w xxx \) ]
then
echo "The file is not readable and writable."
fi
./testfile # testfileを実行すると、xxxが読み書きできないため、if文の中が実行される。
The file is not readable and writable.trap action signal...このシェルスクリプトが、signalに指定したシグナルを受け取ったらどういう処理をするかを actionに指定します。actionはコマンドを並べたものです。
type nametypeコマンドは、nameで指定したコマンドがどういった種類のシェルか、 コマンド本体のパスはどこかを出力します。
type echo
echo is a shell builtin
echo is /bin/echotype date
date is /bin/datetype cd
cd is an alias for nocorrect cd
cd is a shell builtin
cd is /usr/bin/cdumask 022ファイルを作るときにどういう権限で作るかを決定します。
wait jobnumber引数にプロセスIDをしてすると、シェルスクリプトの中でバックグラウンドで走らせた 処理が終わるのを待ちます。
引数に何も指定しない場合、そのシェルから派生している子供のプロセス が全部終了するまで待ちます。