普段はあまり意識しませんが、採用しているシェルが異なる環境などでは、組み込みコマンドか否かでコーディングが変わるため、注意する必要があります。
組み込みコマンドとは?
Linuxで使用可能なコマンドは、/binや/sbin、/usr/binなどのディレクトリに収められているプログラムのほかに、組み込みのコマンドが存在します。どのような組み込みコマンドがあるのかを調べるには、helpコマンドを使用することで表示されます。
コマンドは大きく分けて下記の2種類存在し、いずれもシェルスクリプト中で使用できます。
組み込みコマンド
- 組み込みコマンド
- 外部コマンド
OSのインストール時などに導入されるコマンドを外部コマンドと呼びます。OSによっても細かい内容は異なりますし、サードパーティーが用意したものも数多く存在します。
ここから、各組み込みコマンドについて、動作と使い方を見ていきましょう。
基本組み込みコマンド
ヌルコマンド「:」
「:(ヌルコマンド)」は、何もしないがいつも成功する(真の状態を返す)コマンドです。実行終了ステータスで「0」を返します。いつも真の値を返すので、条件判定を必ず真にしたい場合によく使われます。
while文の場合には以下のように書き表わします。
停止条件を記述せずに実行すると、無限ループに入ってしまうため注意してください!
例はwhile文での実行例を挙げていますが、ヌルコマンドは、while文に限らず、if文などでも使用可能です。
「if」文における処理無しの例
if [ <条件式> ]; then
: 👈 「:」コマンドにより終了ステータス0が返り、処理を何も実行しない
fi
「:(ヌル)」コマンドは、パラメータ展開やリダイレクトだけを行って、コマンドは実行したくない場合や、if/for/while文のリストで何もコマンドを実行したくない場合にも使用されます。
$ : > test_file 👈 test_fileという名前のファイルサイズゼロのファイルができる
ドットコマンド「.」
普通のコマンドとは異なり、新しくプロセスを作らずに現行のシェルプロセスを使って指定されたファイルを読み込み実行します。その結果、指定されたファイルで記述されている変数や関数が、現行のシェルで有効に使えるようになります。
「.」コマンドの終了ステータスは、読み込んだファイル中で実行された最後のリストの終了ステータスになります。ただし、ファイル中にリストが1つもない場合は、終了ステータスは「0」になります。
簡単なシェルスクリプト「outer_file.sh」を作成し、コンソール上から「.(ドット)」で読み込ませ、実行させてみます。
[ outer_file.sh ]
#!/bin/sh
echo "これは読み込まれた外部ファイルから出力しています。"
下記の「.(ドット)」コマンドを使って、外部ファイルをコンソール上へ読み込ませます。
$ . outer_file.sh
実際に、「.(ドット)」コマンドを使ってコンソール上で実行してみます。
[root@CentOS7 bin]# . outer_file.sh これは読み込まれた外部ファイルから出力しています。
読み込んだシェルスクリプト「outer_file.sh」内部の「echo」コマンドから、直接コンソール上へ出力されているのが分かります。
breakコマンド「break」
「for」文 or「while」文でループを扱っている場合、ループを抜けて次の処理に移行できます。break n (n=1,2,3,....)と入力すると、n回入れ子になったループを抜けられます。nの数値を省略するとbreak 1と同じになります。
breakコマンドによってループを抜けると、終了ステータスは「0」になります。
for i in a b c d
do
if [ "${i}" = "b" ]; then
break
fi
echo "変数[ ${i} ]のループ"
done
実行例)
[root@CentOS7 ~]# for i in a b c d > do > if [ "${i}" = "b" ]; then > break > fi > echo "変数[ ${i} ]のループ" > done 変数[ a ]のループ
変数${ i }の値が「b」になった時点でforループを抜けてしまうため、コンソール上へは「a」のみ出力されています。
※ 変数の${i}の値が「b」に変わった後の判定文でforループを抜けてしまうため、「変数bのループ」メッセージは出力されません。
continueコマンド「continue」
breakとは異なり、「for」文 or「while」文でループを扱っている場合、ループを抜けずに次のループに移行する場合に用います。breakと同様の記載方法ですが、 continue n (n≧2) とした場合は、その分だけ外側のループまで戻り、そちらで次のループに移行します。
continueコマンドによって次のループに進むと、終了ステータスは「0」になります。
for i in a b c d
do
if [ "${i}" = "b" ]; then
continue
fi
echo "変数[ ${i} ]のループ"
done
実行例)
[root@CentOS7 ~]# for i in a b c d > do > if [ "${i}" = "b" ]; then > continue > fi > echo "変数[ ${i} ]のループ" > done 変数[ a ]のループ 変数[ c ]のループ 変数[ d ]のループ
一見「break」コマンドの動作に似ていますが、「continue」コマンドでは、ループを抜けることはありません。
変数${i}の値が「b」の時、次のループへ移行している為、「変数bのループ」メッセージだけが出力されていません。
cdコマンド「cd」
実行中のシェルの作業ディレクトリを変更します。引数のディレクトリ名を省略した場合は、"$HOME"が指定されたものとみなされます。
# カレントディレクトリの一階層上に移動する
$ cd ../
# 直前の作業ディレクトリに移動する
$ cd -
下記のページで「cd」コマンドを使った処理を行っています。ご参考まで!
evalコマンド「eval」
引数に与えた文字列をコマンドとして実行します。引数が変数の場合、展開した結果をコマンドとして実行します。解釈の結果、実行されたコマンドの終了ステータスが、evalコマンドの終了ステータスになります。
これはちょっとややこしいので注意してください!
例えば、まず「var1=date」を宣言して、さらに「var2=${var1}」として変数${var2}の中に変数${var1}を代入したとします。目的としては「echo ${var2}」とし場合に「現在の日時(yyyy年 mm月 dd日 土曜日 hh:mm:ss JST)」を出力させることです。
要するにシェルコマンドの2重展開がしたい場合です。実際にシェルとして記述すると下記になります。
$ var1=date
$ var2=${var1}
$ echo ${var2}
実行例)
[root@CentOS7 bin]# var1=date [root@CentOS7 bin]# var2=${var1} [root@CentOS7 bin]# echo ${var2} date
上記の実行例では、「var2=${var1}」として変数${var2}の中に変数${var1}を代入したにも関わらず、結果が文字列「date」として出力されてしまっています。
目的は、この文字列として出力された「date」をコマンドとして認識させたい!
そこで「eval」コマンドを使用します。
$ var1=date
$ var2=${var1}
$ eval ${var2}
一部の「echo」コマンドを「eval」コマンドへ修正して、再実行します。
[root@CentOS7 bin]# var1=date [root@CentOS7 bin]# var2=${var1} [root@CentOS7 bin]# eval ${var2} 2020年 4月 18日 土曜日 13:44:00 JST
「eval」コマンドを使って、文字列として出力された「date」を、無事にコマンドとして認識させることが出来ました。
下記のページで「eval」コマンドを使った処理を行っています。ご参考まで!
execコマンド「exec」
execコマンドは、新しくプロセスを作らず現行のカレントシェルのプロセスと置き換えて、引数のコマンドを実行させます。
※exec以降に記述されたコマンドは実行されません。execコマンドにリダイレクト先のみ記述すると、現行シェルすべてに対してリダイレクト処理を行わせることが出来ます。このコマンドを実行したら、もう元のシェルに戻ることはありません。
引数で指定したコマンドが正常に起動できた場合、シェルには戻らないため、終了ステータスはありません。コマンドが起動できなかった場合は終了ステータスは「0」以外になります。引数を指定せず、リダイレクトのみを行った場合、正常にリダイレクトが行われれば終了ステータスは「0」になります。
# 現行シェルの標準出力/標準エラー出力がログに出力される
exec >> /var/log/messages 2>&1
# (※1)
exec cd /usr/bin/
exec echo hello
※1:execコマンドで「cd」が起動された時点でシェルスクリプトのプロセス自体が「cd」のプロセスと置き換わります。よってそのあとの「exec echo hello」コマンドは実行されません。「cd」が終了したらこのシェルスクリプトは終了してしまいます。
exitコマンド「exit」
exitコマンドを実行すると、その時点でシェルスクリプトが終了します。引数の終了ステータスで終了ステータスを指定できます。引数に整数を与えると、終了コードがその値になります(デフォルトは0)。
#!/bin/sh
# 終了コード1で終了する
exit 1
「exit」と「return」の違い
- 「exit」:終了コードの値に関わらず、現在のプロセスを終了させます。プロセスを閉じてしまうため、実行中のコンソール自体が終了します。
- 「return」:関数内のみで使用可能です。「return」コマンド実行後は、元の命令に戻ります。実行中のコンソールは終了しません。
終了ステータスコードの一覧 (bash)
終了ステータス | 意味 |
1 | 一般的なエラー |
2 | ビルトインコマンドの御用 |
126 | 実行不可(実行権不足)等 |
127 | 未検知(対象が存在しないコマンド)等 |
128 | 「exit」コマンドへ不正な値(文字列)等が設定された |
128+n | シグナル「n」で終了 |
255 | 範囲外の終了ステータス |
exportコマンド「export」
exportコマンドを実行すると、引数の変数名で指定されたシェル変数が環境変数としてエクスポートされます。exportコマンドを引数なしで実行した場合は、現在エクスポート中の環境変数の一覧が表示されます。
環境変数?
exportコマンドの終了ステータスは「0」になります。ただし、変数名の指定が正しくないなどexportコマンド自体がエラーになった場合は、終了ステータスは「0」以外になります。
今後コマンドで下記の環境変数を用いると、以降は変数宣言無しで値が参照できるようになります。プログラムから起動された子プロセスにも、環境変数は引き継がれます。
BASE_PATH=${BASE_PATH:-"/root/scripts"}
DTIME=`date`
export BASE_PATH DTIME
主な使用用途としては、システム単位で使用する「規定ディレクトリ」や「実行ディレクトリ」等を設定することが一般的です。
getoptsコマンド「getopts」
シェルに対して"-"と"アルファベット一文字"でオプションを指定された場合、それを解析します。オプションによって挙動を変えたい時にcase文と共に用います。
解釈の結果、オプションが見つかった場合は終了ステータスは「0」になります。オプションではない引数まで解釈が進んだ場合は終了ステータスは「0」以外になります。
--helpなどのいわゆるロングオプションを使う場合は、外部コマンドのgetoptを使うことが多いです。
#!/bin/sh
#-a /-b オプションを指定した場合に出すメッセージを変更する
while getopts a:b: opts
do
case $opts in
a) echo "引数:${OPTARG}" ;;
b) echo "引数:${OPTARG}" ;;
*) rc=1 ;;
esac
done;
上記のスクリプトを、シェルスクリプト「func.sh」に記述して実行してみます。
[root@CentOS7 bin]# sh func.sh -a aiueo 引数:aiueo [root@CentOS7 bin]# sh func.sh -b babibubebo 引数:babibubebo
シェルスクリプトを作成する上で、「getoptsコマンドなくしてシェルとは呼べず」と言われるほど、重要な組み込みコマンドです。
下記のページで「getopts」コマンドを使った処理を行っています。ご参考まで!
readコマンド「read」
キーボードなどデバイスからの入力を変数にセットします。対話式スクリプトを作る際に用います。標準入力がEOF(EndOfFile)にならないかぎり、終了ステータスは「0」になります。
#!/bin/sh
#ユーザーが入力したデータをstrに代入
read str1 str2 str3
#strに代入されたデータを表示
echo "str1:$str1" "str2:$str2" "str3:$str3"
上記のスクリプトを、シェルスクリプト「func.sh」に記述して実行してみます。
[root@CentOS7 ~]# sh func.sh No.1 No.2 No.3 👈 キーボードから「No.1 No.2 No.3」と入力 str1:No.1 str2:No.2 str3:No.3
readonlyコマンド「readonly」
変数名で指定された変数をリードオンリー(書き換え不可)にします。これを設定した後では、その変数の操作(set or unset)が不可能となります。
readonlyコマンドの終了ステータスは「0」になります。ただし、変数名の指定が正しくないなど、readonlyコマンド自体がエラーになった場合は終了ステータスは「0」以外になります。
#この記述以降にVALUE変数を変更しようとするとエラーメッセージが出る
$ VALUE="Not OverWrite"
$ readonly VALUE
シェル変数${VALUE}へ「readonly」を付与した後に、文字列”aaa”の代入を行ってみます。
[root@CentOS7 ~]# VALUE="Not OverWrite" [root@CentOS7 ~]# readonly VALUE [root@CentOS7 ~]# VALUE="aaa" -bash: VALUE: 読み取り専用の変数です
returnコマンド「return」
シェルの関数から抜 けるコマンドです。関数の終了ステータスを決定して終了させます。終了ステータス番号が指定されなかった場合には、関数が終了する直前のコマンドの実行終了コードが返ります。
func() {
echo `date`
return 255
}
[root@CentOS7 com]# func() { > echo `date` > return 255 > } [root@CentOS7 com]# func 2020年 5月 26日 火曜日 12:28:23 JST [root@CentOS7 com]# echo $? 255
リターンコードが「255」で返却されていることが分かります。
「exit」と「return」の違い
- 「exit」:終了コードの値に関わらず、現在のプロセスを終了させます。プロセスを閉じてしまうため、実行中のコンソール自体が終了します。
- 「return」:関数内のみで使用可能です。「return」コマンド実行後は、元の命令に戻ります。実行中のコンソールは終了しません。
上記の例の場合、dateを実行するだけの関数だとほぼ終了ステータスコードは「0」ですが、returnコマンドを使っているので必ず255が返されます。
終了ステータスコードの一覧 (bash)
終了ステータス | 意味 |
1 | 一般的なエラー |
2 | ビルトインコマンドの御用 |
126 | 実行不可(実行権不足)等 |
127 | 未検知(対象が存在しないコマンド)等 |
128 | 「exit」コマンドへ不正な値(文字列)等が設定された |
128+n | シグナル「n」で終了 |
255 | 範囲外の終了ステータス |
shiftコマンド「shift」
位置パラメタの値を($2を$1に、$3を$2にというように)左にずらします。
shift [n]
引数として[n]のところに指定した数値の分だけずらします。
func() {
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
shift
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
shift 3
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
}
9個の引数を与えてこのシェルスクリプトを実行してみます。
[root@CentOS7 com]# func() { > echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 > shift > echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 > shift 3 > echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 > } [root@CentOS7 com]# func 1 2 3 4 5 6 7 8 9 -bash 1 2 3 4 5 6 7 8 9 -bash 2 3 4 5 6 7 8 9 -bash 5 6 7 8 9
8行目:1から9までの数値を引数にして、スクリプトを実行しています。
9行目:すべての引数がそのまま位置パラメタの値として表示されています。
10行目:位置パラメタを1個シフトしたために、$1(数値2)から$8(数値9)までが表示されました。※ 値もそれぞれずれていき、最初に$1に代入されていたものがなくなっています。
11行目:次に3個シフトさせたので、$1には最初に$5に代入されていた値が入り、残りの数値が表示されました。ちなみに、シェルスクリプトの最初で位置パラメタを全部クリアさせたい場合には、以下のように記述します。
# 全パラメータのクリア
shift $*
trapコマンド「trap」
シェルスクリプト内で、指定した(複数書けます)シグナルを受け取ったときにどういう処理をするかを指定します。
引数のコマンドとして空文字列を指定した場合は、指定のシグナルがシェルによって無視されるようになります。引数のコマンドを省略した場合は、指定のシグナルの設定が解除されます。エラーが発生しない限り、終了ステータスは「0」が返ります。
msg="トラップを拾いました。"
trap `echo ${msg}` 1 2 3 15
シグナル番号一覧
シグナル | シグナル名 | 意味 |
---|---|---|
0 | - | プロセス終了時に送出する EXIT シグナル |
1 | HUP | ハングアップシグナル |
2 | INT | 割り込みシグナル(Ctrl+C や Del キー) |
3 | QUIT | プログラム実行中止のクイットシグナル |
9 | KILL | プロセスの強制終了 ※ 故意による強制終了なのでtrapでは拾えない |
15 | TERM | プロセスを終了させるための終了シグナル |
下記のページで「trap」コマンドを使った処理を行っています。ご参考まで!
typeコマンド「type」
「type」コマンドは、引数で指定したコマンドが、どういう取り扱いなのかを出力します。つまり、組み込みコマンドかどうかや、コマンド本体のある場所を教えてくれます。
$ type cd echo
実行例)
[root@CentOS7 bin]# type cd echo cd はシェル組み込み関数です echo はシェル組み込み関数です
umaskコマンド「umask」
「umask」コマンドは、ファイルを生成するときにどういうモード(読み・書き・実行)で作るかを決定します。
umaskコマンドを実行すると、引数で指定されたマスク値(8進数)がシェル自身のumask値として設定されます。umaskコマンドを引数なしで実行すると、現在のumask値を表示します。
$ umask マスク値
下記のページで「umask」コマンドを使った処理を行っています。ご参考まで!
unsetコマンド「unset」
「unset」コマンドは、指定した変数や関数を消去します。現在セットされている変数や関数の名称を引数に指定します。複数指定することも可能です。
$ var="これはテスト変数です。"
$ echo ${var}
# 変数${var}を削除
$ unset var
$ echo ${var}
実行例)
[root@CentOS7 bin]# var="これはテスト変数です。" [root@CentOS7 bin]# echo ${var} これはテスト変数です。 [root@CentOS7 bin]# unset var [root@CentOS7 bin]# echo ${var}
ここまでざっと紹介してきましたが、他にも色々な使い方があったり、別の組み込みコマンドが存在するので、ぜひmanコマンド(これも組み込みコマンド)を使って調査してみる事をお勧めします。
外部組み込みコマンド
一部の組み込みコマンドについては、シェルが直接コマンド機能を実行して処理を高速化させるため、外部コマンドにも同じものがあるにもかかわらず組み込みコマンドとして実装されているものがあります。
POSIXの下では外部コマンドにない物は組み込みコマンドに存在しないというのが基本になりますが、例外もあります。細かい挙動が異なってくることから、目的の処理が出来ない事があるのでそれぞれ見ていきましょう。
基本的に組み込みコマンドの挙動はbashの物をもとにしていますが、一部別のシェルを参照するものもあります。
echoコマンド「echo」
標準出力に引数の文字列を出力するコマンドです。「echo」コマンドはシェルの組み込みコマンドとしても普通のコマンドとしても提供されています。終了ステータスは「0」になります。
コマンドの書式
echo [オプション] メッセージ
コマンドの主なオプション
- -e:最後の改行が出力される。
- -n:最後の改行が出力されない。
$ echo "Beエンジニア"
代表的な違いとして、一部シェルの組み込みコマンドで使用可能な「-e(エスケープシーケンスを有効にする)」オプションが、組み込みコマンド(/bin/echo)においては使用不可能です。
FreeBSDの外部コマンドのechoや、SunOS4.xのshのechoなど、-nオプションのみが使えて-eオプションが使えないechoも存在します。
「echo」コマンドは、シェルの操作において、非常に多用されるコマンドです。メッセージを出力する場合は、「'(シングルクォート)」で囲み、引数を一つにまとめて渡すことが推奨されます。
trueコマンド「true」とfalseコマンド「false」
「true」コマンドは、常に終了コードを0で返すコマンドです。「false」コマンドは、常に終了コードを「1」で返すコマンドです。両者とも引数はすべて無視されます。
組み込みコマンドにはオプションがありませんが、外部コマンド版には--help(ヘルプの表示)と、--version(コマンドのバージョンの表示)が存在します。
「true」コマンド「false」コマンドを使用して「0」「1」が返るか確認してみましょう。
# trueコマンドの実行
$ true
$ echo $?
# falseコマンドの実行
$ false
$ echo $?
コンソールへ直接手入力して、終了ステータスコードを確認します。
[root@CentOS7 ~]# true [root@CentOS7 ~]# echo $? 0 [root@CentOS7 ~]# false [root@CentOS7 ~]# echo $? 1 [root@CentOS7 ~]#
「true」コマンドや「false」コマンドの直後に特殊パラメータ$?を参照すると、それぞれ「0」や「1」の値が表示されることがわかります。
killコマンド「kill」
引数として持たせたプロセスにシグナルを送信するコマンドです。シグナルが正常に送信できた場合、または「kill -l」を実行した場合は、終了ステータスは「0」になります。
デフォルトでは終了のシグナルを送るため、ハングアップしたプロセスを強制終了させるなどしたいときに使う事が多いコマンドです。
コマンドの書式
kill [オプション] プロセスID
コマンドの主なオプション
- -s:プロセスに送るシグナル名または番号 -シグナル名、-番号でも指定可能
- -l:指定可能なシグナルの一覧を表示する
組み込みコマンドでは-s オプションで送るシグナル番号の指定、-l オプションでシグナル名の指定、プロセスIDの指定以外に、ジョブIDでの指定が可能ですが、外部コマンド版ではこれらの機能はついていません。
# シグナルの一覧を表示します。
$ kill -l
上記のコマンドを実行すると、指定可能なシグナルの一覧が表示されます。具体的な表示内容はOSにより異なります。
[root@CentOS7 ~]# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
シグナル番号一覧
「-s」オプション指定時のシグナル番号については、下記参照!
※ 通常は下記テーブル中のシグナル番号、シグナル名から選択されることが多いです。
シグナル | シグナル名 | 意味 |
---|---|---|
0 | - | プロセス終了時に送出する EXIT シグナル |
1 | HUP | ハングアップシグナル |
2 | INT | 割り込みシグナル(Ctrl+C や Del キー) |
3 | QUIT | プログラム実行中止のクイットシグナル |
9 | KILL | プロセスの強制終了 ※ 故意による強制終了なのでtrapでは拾えない |
15 | TERM | プロセスを終了させるための終了シグナル |
printfコマンド「printf」
入力されたデータを整形して表示する事が可能なコマンドです。エラーが発生しない限り終了ステータスは「0」になります。
一部のシェルの組み込みコマンドでのprintfコマンドでは\xHH(Hは数字)などの16進数表記を受け付け、対応した文字を出力しますが、外部コマンドにそのような機能はありません。
8進数の表記を用いるか、16進数の表記をしないようにしましょう。また、8進数での記述でも、一部のシェルで異なるコードを指定したと認識する場合があります。
とはぁ、この辺はごちゃごちゃ言っても理解はむずかしいと思います。主な使用用途は、文字列の整形と思っていただいて結構です。
「慣れるより慣れろ!」です。直接触ってみましょう。
echo "aaaa" "bbbb" "cccc"
上記コマンドの出力結果は、「aaaa bbbb cccc」となります。目的としては、2つ目の文字列「bbbb」を「[ ](鉤括弧)」等を使って”[ bbbb ]”(こんな感じ)で整形したい場合があります
# 文字列を「[ ](鉤括弧)」を使って整形する
$ printf "%s [%-4s] %s\n" "aaaa" "bbbb" "cccc"
見た方が速いと思います。実行してみましょう。
[root@CentOS7 ~]# printf "%s [%-4s] %s\n" "aaaa" "bbbb" "cccc" aaaa [bbbb] cccc
見事に整形できました!
つまり「printf」を使ってその後の引数で整形ロジックを組み立てているのです。
「printf」コマンドの直後の暗号みたいな「%s」は文字列を表します。一番初めに記述されているので"aaaa"、"bbbb"、"cccc"のうち、一番目の文字列"aaaa"に該当します。
次の呪文”[%-4s]”は、2番目に記述されているので、2番目の文字列"bbbb"を対象としています。つまり2番目の文字列(4文字)を「[ ](鉤括弧)」で括れという呪文です。
もっと詳しく
最後の"%s\n"は、残りの文字列を出力して「改行」を指示している呪文です。
ちなみに”%-4”を”%-5”へ変更してみます。(2番目の文字列"bbbb"を左から遡って5文字後に"]"で括る様に指示)
[root@CentOS7 ~]# printf "%s [%-5s] %s\n" "aaaa" "bbbb" "cccc" aaaa [bbbb ] cccc
結果は"[bbbb ]"となり、文字列の右側1文字分空白になって不格好ですが、指示通りに整形されているのが分かります。
使う機会はあまり多くはありませんが、「ここぞ!」と言う時に、非常に役に立つので覚えておいて損はありません。
pwdコマンド「pwd」
現在の作業ディレクトリ(カレントディレクトリ)を表示するコマンドです。コマンドの実行がエラーにならない限り終了ステータスは「0」になります。
シェルの組み込みコマンドの場合は、-Lオプションか、-Pオプションが指定できますが外部コマンドにはそのような機能はありません。
コマンドの主なオプション
- -P:物理的なディレクトリの位置を表示する。元のファイルまで表示しない
- -L:変数${PWD}の値を表示。シンボリックリンクの元のファイルまで表示する
testコマンド「test」
引数として持たせた条件式の真偽を判定するコマンドです。主に条件に合うファイルの有無の判定などに使われますが、外部コマンドの場合はサポートされている-nt(newer than)、-ot(older than)オプションは、shの組み込みコマンドではサポートされていません。
条件式の評価結果が真ならば終了ステータスは「0」に、偽ならば終了ステータスは「1」になります。
コマンドの書式
test 条件式(※1)
[ 条件式 ](※2)
※1:testコマンドを使用して記述した場合の表記。
# testコマンドでの判定表記(※1)
$ a="文字列1"
$ b="文字列2"
$ echo `test "$a" = "$b" && echo "同じ文字列ですね" || echo "違う文字列ですね"`
[root@CentOS7 ~]# a="文字列1" [root@CentOS7 ~]# b="文字列2" [root@CentOS7 ~]# echo `test "$a" = "$b" && echo "同じ文字列ですね" || echo "違う文字列ですね"` 違う文字列ですね [root@CentOS7 ~]#
※2:「[ ]」を使用して記述した場合の表記。
# [ ] での判定表記(※2)
$ a="文字列1"
$ b="文字列2"
$ echo `[ "$a" = "$b" ] && echo "同じ文字列ですね" || echo "違う文字列ですね"`
[root@CentOS7 ~]# a="文字列1" [root@CentOS7 ~]# b="文字列2" [root@CentOS7 ~]# echo `[ "$a" = "$b" ] && echo "同じ文字列ですね" || echo "違う文字列ですね"` 違う文字列ですね [root@CentOS7 ~]#
「test」コマンドは、「test」という名前でも「[ ]」という名前でも起動でき、「 [ 」で起動した場合は最後の引数を「 ] 」にするため、そのコマンドラインは「[ ]」という角カッコで囲んだ状態になります。
拡張組み込みコマンド
builtinコマンド「builtin」
「builtin」コマンドは、bashなどLinuxのシェルが内部に備えているビルトインコマンド(内部コマンド、シェルコマンド)を実行するコマンドです。
実行されたコマンドの終了ステータスが、builtinコマンドの終了ステータスになります。
Linuxのコマンドには、「ll」のような、コマンドの実態「ls -l」と、その実態に文字づくコマンドのエイリアス「ll」が用意されています。
「ll」コマンドは、「ls -l」コマンドのエイリアスです。「type」コマンドで確認してみます。
[root@CentOS7 ~]# type ll ll は `ls -l --color=auto' のエイリアスです
Unix系のOSでは、常にエイリアスを優先させてコマンドを起動します。
「builtin」コマンドは、「builtin」を付けて実行することで、必ずビルトインコマンドを実行できるようになります。
letコマンド「let」
let 変数=式の形で、式の計算結果を変数にセットするコマンドです。インクリメントやビットシフト、ビット演算など多くの算術演算を行えます。
最後の算術式の評価結果が真(「0」以外)なら、算術式の評価の終了ステータスは真(0)に、最後の算術式の評価結果が偽(0)なら、算術式の評価の終了ステータスは偽(1)になります。
シェルの種類によって特殊な記述が可能なコマンドですが、letはシェル組み込みコマンドのみで、外部コマンドは存在しません。
$ let result='100*50'
「let」コマンドでは、計算式をまとめて一つの引数にする必要があります。また不用意に空白を開けると、区切りとして認識されてしまうため、計算式は「'(シングルクォート)」で囲みます。
[root@CentOS7 ~]# let result='100*50' [root@CentOS7 ~]# echo ${result} 5000 [root@CentOS7 ~]# echo $? 0 [root@CentOS7 ~]#
localコマンド「local」
シェル関数の中でローカル変数を宣言するために用いるコマンドです。このコマンドを用いると、変数の値が関数の中でのみ保持されます。
「local」コマンドは、関数の外で宣言された時を除いて常に終了コードが0で返ってくるため、スクリプトの記述によっては意図したエラーハンドリングが出来ない事があります。
localはシェル組み込みコマンドのみで、外部コマンドは存在しません。また、シェルの中でもlocalコマンドが存在しないものがあります。
Shellスクリプト基礎知識(全11記事+1)
├─シェルスクリプトの基本事項!
├─変数と特殊変数について!
├─演算子「算術演算子」「比較演算子」について!
├─条件分岐「if」「case」について!
├─ループ処理「for」「while」について!
├─文字列置換「bash」「sed」について!
├─複数行のテキスト出力!ヒアドキュメントについて!
├─書式?戻り値?シェルスクリプト内の関数について!
├─シェルの組み込みコマンドについて!
├─クォートとは?コマンド置換とは?実現方法と内容の違いについて!
└─リダイレクトとは?標準入力・出力、標準エラー出力等について!
(補足)シェルスクリプトの設計書とは?必要な項目や書き方等を解説!