Bash Basics | Basicsトップページ | トップページ
シェル
bashはGNUプロジェクトにおけるBourne Shellの代替えとして広くLinuxディストリビューションで採用されているシェルです。
bashはコマンドを処理するインタープリタ(プロセッサ)であり、インタラクティブにユーザーが入力するコマンドを実行したり、スクリプトと呼ばれるテキストファイルを読み込んで実行することが可能です。
出典: Bash (Wikipedia)
シェルはUNIXオペレーティングシステム(OS)、およびUnix系OSでOSに対して処理を指示するためのインターフェースとしての役割を持ち、ハードウェアなどのリソースを制御するカーネル(核)の周辺を取り巻く殻(シェル)のようなものであるため、「シェル」と呼ばれています。
ユーザーがOSに対してログインするとGUI環境がある場合を除いてシェルのセッション(ログインシェル)が開始されます。ログインシェルはユーザーごとにカスタマイズすることが可能です。
シェルには多くの派生バージョンがあり、多くはBourne Shell系とC Shell系のシェルに大別されます。
Bourne Shell系
bashは、標準入力やファイルから読み込んだコマンドを実行する、sh互換のコマンド言語インタプリターでKorn Shell(ksh)やC Shell(csh)の便利な機能が採り入れられています。
bashはIEEE POSIX specification(IEEE Standard 1003.1)の「Shell and Utilities」に準拠する実装を目指しており、bash はデフォルトでPOSIX準拠に設定することもできます。
シェルの説明では、下記の用語は以下の定義となります。
シェルで特別な意味を持つ単語がいくつかあり、これらを予約語と呼びます。
シェルの文法上、単純なコマンドで先頭の単語であるか、caseコマンドかforコマンドの3つ目の単語として以下の単語がクォートされずに現れた場合、予約語として認識されます。
!、case、coproc、do、done、elif、else、esac、fi、for、function、if、in、select、then、until、while、{、}、time、[[、]]
本コンテンツでは予約語を赤文字で表記します。
リモートからログインしてユーザーに最初に割り当てられたシェルとして起動されたシェル、および--loginオプション付きで起動されたシェルをログインシェルと言います。
OSに既にログインしているユーザーが端末を起動することで起動されるシェルは非ログインシェルとなります。
ログインシェルはlogin_shellが有効となっているため、このオプションの状態を確認することでログインシェルかどうかを確認することができます。
シェルが標準入力と標準エラー出力がいずれも端末に接続されている状態でオプションではない引き数がなく、-cオプションが指定されていないシェル、または-iオプション付きで起動されたシェルを対話型のシェルと言います。
対話型のシェルはPS1が設定され、特殊パラメータの$-にiが含まれるため、この値を確認することで対話型のシェルかどうかを確認することができます。
シェルは起動時や終了時に設定ファイルを読み込み、初期化したり、後処理を実行します。下表に主なシェルの設定ファイルを示します。
sh | bash | ksh | csh | tcsh | zsh | |
---|---|---|---|---|---|---|
/etc/.login | login | login | ||||
/etc/csh.cshrc | yes | yes | ||||
/etc/csh.login | login | login | ||||
~/.tcshrc | yes | |||||
~/.cshrc | yes | yes ** | ||||
~/.login | login | login | ||||
~/.logout | login | login | ||||
/etc/profile | login | login | login | login | ||
~/.profile | login | login * | login | login | ||
~/.bash_profile | login * | |||||
~/.bash_login | login * | |||||
~/.bash_logout | login | |||||
~/.bashrc | interact + n/login | |||||
/etc/zshenv | yes | |||||
/etc/zprofile | login | |||||
/etc/zshrc | interact | |||||
/etc/zlogin | login | |||||
/etc/zlogout | login | |||||
~/.zshenv | yes | |||||
~/.zprofile | login | |||||
~/.zshrc | interact | |||||
~/.zlogin | login | |||||
~/.zlogout | login |
*: "~/.bash_profile", "~/.bash_login", "~/.profile"の順に最初に読み込み可能なファイルのみを読み込みます。"sh"として起動された場合は、"~/.profile"のみを読み込みます。
**: "~/.tcshrc"がない場合のみ読み込みます。
出典: Unixシェル (Wikipedia)
シェルは下記に示す単純なコマンド、パイプライン、リスト、複合コマンド、コプロセス、関数定義を記述することができます。
シェルでは変数の代入を並べたあとに(変数の代入は省略可能です)ブランクで区切られた単語とリダイレクションに続いて、最後に制御演算子を記述したものが単純なコマンドです。
[変数の代入1 [変数の代入2]...] 単語1 [単語2]...[リダイレクション] 制御演算子
シェルは単純なコマンドを以下に示す展開、代入、リダイレクションを左から右に記述された順で実行します。
$ echo "Hello World"
Hello World
この例では変数の代入はなく、echoコマンドとその引き数"Hello World"と制御演算子である改行文字が入力されています。$ LANG=C man bash
BASH(1) General Commands Manual BASH(1)
NAME
bash - GNU Bourne-Again SHell
SYNOPSIS
bash [options] [file]
COPYRIGHT
Bash is Copyright (C) 1989-2011 by the Free Software Foundation, Inc.
DESCRIPTION
Bash is an sh-compatible command language interpreter that executes
commands read from the standard input or from a file. Bash also incor-
porates useful features from the Korn and C shells (ksh and csh).
Bash is intended to be a conformant implementation of the Shell and
Utilities portion of the IEEE POSIX specification (IEEE Standard
1003.1). Bash can be configured to be POSIX-conformant by default.
OPTIONS
All of the single-character shell options documented in the descrip-
tion of the set builtin command can be used as options when the shell
Manual page bash(1) line 1 (press h for help or q to quit)
この例ではシェル変数LANGに値Cを代入してmanコマンドとその引き数bashと制御演算子である改行文字が入力されています。$ x='Hello' y='world!' echo $x $y
上記の例では変数xに代入されたHelloと変数yに代入されたworld!がechoコマンドで出力されることを期待していると思いますが期待通りに出力されていません。$ x=abc
$ y=xyz
$ x='Hello' y='world!' echo $x $y
abc xyz
それでは、最初の例を期待通りに実行させるためにはどのようにすれば良いでしょうか?$ x='Hello' y='world!' bash -c 'echo $x $y'
Hello world!
この記述方法では変数xとyに値を代入したのち、bashコマンドを実行しますが、その引き数はシングルクォーテーションで囲まれているため文字列'echo $x $y'となります。$ x='Hello' y='world!' bash -c "echo $x $y"
この例も期待通りに動作していません。コマンドを実際に使用する場合、あるコマンドの実行結果(である標準出力)を別のコマンドでさらに処理したいということがよくあります。
例えば、あるファイルからデータを抽出して、それを整形したものをさらにソートするということが考えられます。
シェルの機能であるパイプラインを利用することでこれが可能となります。最も簡単なパイプラインは連結したいコマンドを | で並べて記述するだけです。
パイプラインを使うと記述した順に左側のコマンドの標準出力をその右側のコマンドの標準入力としてデータを引き継ぐ(連結する)ことができます。
パイプラインの連結は各コマンドのリダイレクションよりも先に実行されるため、各コマンドに標準入出力のリダイレクションがある場合、それぞれの指定で上書き(優先)されます。
|& による標準エラー出力の連結は各コマンドのリダイレクションよりも後に実行されるため、各コマンドの標準エラー出力のリダイレクションがある場合、その指定を上書きします。
[time [-p]] [!] コマンド1 [[|] コマンド2 ...]
または
[time [-p]] [!] コマンド1 [[|&] コマンド2 ...]
パイプラインは何段も連結することができるので、コマンド1 | コマンド2 | コマンド3 | コマンド4のように実行することも可能です。
| ではなく、|& でパイプラインを繋ぐと前段のコマンドの標準エラー出力もパイプを通して後段のコマンドの標準入力に連結することができます。
これは下記の短縮形です。
コマンド1 2>&1 | コマンド2
つまり、上記パイプラインは下記と等価です。
コマンド1 |& コマンド2
例えば、あるディレクトリの一覧をlsコマンドで取得し、その一覧をwcコマンドに連結することでディレクトリに存在するファイル数をカウントすることが可能です。
$ ls | wc -l
12
上記の結果では合計で12のファイル(ディレクトリを含む)が存在しています。$ ifconfig | grep -w inet | awk -F" " '{print $2}' | sort
127.0.0.1
192.168.1.10
192.168.10.10
パイプラインでコマンドを連結した場合の終了ステータスは以下の通りとなります。
|
echoコマンドで"Hello World"を出力し、パイプラインでtrコマンドに連結して英大文字に変換しています。 最後段のtrコマンドの終了ステータスである0が返されます。 |
|
echoコマンドで"Hello World"を出力し、パイプラインでtrコマンドに連結して英大文字に変換しています。 最後段のtrコマンドの終了ステータスである0を論理否定した1が返されます。 |
|
コマンドのスペルが間違っているため、前段のコマンドは失敗しています。 パイプラインで標準エラーのメッセージも連結しているため、エラーメッセージがtrコマンドで英大文字に変換されています。 最後段のtrコマンドの終了ステータスである0が返されます。 |
|
コマンドのスペルが間違っているため、前段のコマンドは失敗しています。 パイプラインで標準エラーのメッセージも連結しているため、エラーメッセージがtrコマンドで英大文字に変換されています。 最後段のtrコマンドの終了ステータスである0を論理否定した1が返されます。 |
|
最後段のtrueコマンドの終了ステータスである0が返されます。 |
|
最後段のtrueコマンドの終了ステータスである0を論理否定した1が返されます。 |
|
pipefailオプションが有効化されている場合、最も後段の0以外の終了ステータスを返すfalseコマンドの終了ステータスである1が返されます。 !をパイプラインの前に指定した場合はその値を論理否定した0が返されます。 |
|
echoコマンドで"Hello World"をfileにリダイレクションして、パイプラインでcatコマンドに接続しています。 パイプラインよりもリダイレクションが後に行われるため、何も出力されません。 |
|
存在しないコマンドcmdcmdを実行しようとしてエラーが発生しています。それを |& でパイプラインを使ってcatコマンドの標準入力に接続しています。 標準エラー出力のリダイレクションよりもパイプラインの接続が後で行われるため、エラーメッセージがcatコマンドの標準入力と接続され、出力されます。 |
|
シェルのPOSIXモードを解除してtimeの直後に改行文字を入力すると、何も実行せずに時間情報を出力するため、全て0秒と表示されます。 |
|
シェルがPOSIXモードの時、timeの直後に改行文字を入力すると、シェルと子プロセスがそれまでに消費したユーザー時間とシステム時間が表示されます。 |
|
カレントディ レクトリに左記のようなスクリプトtimeを作成します。 |
|
PATHの先頭にカレントディレクトリを追加します。 シェルのPOSIXモードを解除してtimeの直後に-pを付加して、sleepコマンドを実行すると、外部コマンドのsleepを実行し、実行にかかった時間情報を出力します。 この時、timeは-pオプションが指定されたと認識し、出力形式はPOSIX仕様となります。 シェルがPOSIXモードの時、timeの直後に-pを付加して、sleep 1を入力すると、timeは予約語として認識されないため、外部コマンドとして解釈され、PATHからコマンドを検索し、カレントディレクトリのtimeが実行されます。 |
1つ以上のパイプラインを以下のいずれかの制御演算子で区切って並べたものをリストと呼びます。
パイプラインの最後に;、&、改行文字を記述することもできます。
制御演算子 | 説明 |
---|---|
& | &の前に記述されたパイプラインをサブシェル内でバックグラウンドで実行します。この(&の前に記述された)パイプラインの終了ステータスは常に0となります。 &の次にパイプラインの記述があれば、前のパイプラインの終了を待たずに&の次に記述されたパイプラインを実行します。 |
; | ;の前に記述されたパイプラインをフォアグランドのサブシェル内で実行し、そのパイプラインの終了を待ってから;の次に記述されたパイプラインを順番に実行します。 |
改行文字 | 改行文字の前に記述されたリストまたは、パイプラインをフォアグラウンドのサブシェル内で実行します。 |
&& | &&の前に記述されたパイプラインをフォアグラウンドのサブシェル内で実行し、そのパイプラインが終了ステータス0を返した場合に限って、&&の次に記述されたパイプラインを実行します。 |
|| | ||の前に記述されたパイプラインをフォアグラウンドのサブシェル内で実行し、そのパイプラインが0以外の終了ステータスを返した場合に限って、||の次に記述されたパイプラインを実行します。 |
|
echoコマンドを全て;で区切って記述しているため、順番に実行されます。 |
|
echoコマンドを全て&で区切って記述しているため、それぞれバックグラウンドで実行され、処理が終了したものから出力されます。このため、出力順はそのたびに不定となります。 |
|
trueとfalseを使って終了ステータスによる違いを示しています。 &&の場合、直前のコマンドが終了ステータス0で終了した時のみ、次のコマンドが実行されていることがわかります。 一方で||の場合、直前のコマンドが0以外の終了ステータスで終了した時のみ、次のコマンドが実行されていることがわかります。 |
下記のようにコマンドが予約語coprocで始まる場合、制御演算子&をコマンドに付加した時と同じようにサブシェル内で非同期に実行されます。
コプロセスとして非同期に実行されたコマンドと実行したシェルの間には双方向のパイプが生成され、標準入出力を介してデータをやり取りすることができます。
coproc [コプロセス名] コマンド [リダイレクション]
コプロセス名は複合コマンドの場合に指定することができます。それ以外の場合にコプロセス名を指定しようとすると、単純なコマンドの最初の単語として認識されます。コプロセス名を指定しなかった場合のデフォルトの名前はCOPROCとなります。
コプロセスとしてコマンドを実行するとシェルに指定したコプロセス名(指定しなかった場合は、COPROC)の配列変数が生成されます。
実行されたコマンドの標準入力と標準出力がシェルのファイルディスクリプタの1つとそれぞれパイプによって接続されます。
実行されたコマンドの標準出力が接続されるファイルディスクリプタは配列変数 コプロセス名[0] に代入され、実行されたコマンドの標準入力が接続されるファイルディスクリプタは配列変数 コプロセス名[1] に代入されます。
コプロセスのパイプはコマンドのリダイレクションよりも先に実行されるため、コマンドの標準入出力のリダイレクションを指定した場合、指定されたリダイレクションで上書き(優先)されます。
ファイルディスクリプタは単語展開により、シェルのコマンドの引き数やリダイレクションに指定することもできます。
コプロセスの実行で生成されたサブシェルのプロセスIDは変数 コプロセス名_PID に代入されます。
実行例はコプロセスとのパイプを参照してください。
$ STR="Hello World"; (STR='Hello World!!'; echo ${STR};); echo $STR
Hello World!!
Hello World
$ set -- apple orange; (set -- grape lemon; echo $@); echo $@
grape lemon
apple orange
$ DATE=($(date))
$ for ((i=0; i<${#DATE[*]}; i++)); do echo ${DATE[$i]}; done
2022年
3月
13日
日曜日
11:44:49
JST
()とコマンド置換を組み合わせてコマンドの実行結果(標準出力)を変数に代入することができますが、この例の外側の()は配列変数に値を代入するための括弧であり、複合コマンドの括弧ではありません。内側の$()の括弧はコマンド置換となります。$ (i=1;IFS=$'\n'; while read l; do printf "%06d: %s\n" $((i++)) "$l"; done;) <source.sh >source.sh.txt
この例ではsource.shを1行ずつ読み込んで、各行の行頭に6桁の行番号を付加したものをsource.sh.txtとして書き込んでいます。
例として下記のようなスクリプトset.shを作成して確認します。
|
set.shでは変数STRに"Hello Hello"を代入しています。
|
例として下記のようなスクリプトgroup.shを作成して確認します。
|
group.shではカレントディレクトリにある拡張子がtxtの全てのファイルに"Title"という文字列が含まれていた場合、"Subject"に書き換え、 書き換えたファイル名をresultに書き出しています。
|
|
カンマ演算子を使った例です。 左から右に評価されるため、変数iへの代入、変数jへの代入、i*=jの評価が順に行われます。 |
|
上記の例に似ていますが、3つ目のオペランドの変数jが前置インクリメントとなるため、i=i*(j+1)となります。 |
|
論理的ANDを含む例です。 i>jが評価され1を返す(真となる)ため、i-=jが評価されます。 |
|
上記をletで記述した例です。 |
|
算術式中に!を含む場合、クォートが必要です。 履歴展開が有効な場合、ダブルクォートで!をクォートすることはできません。 |
$ touch a
$ if [[ -f a ]]; then echo ファイルが存在します。; fi
ファイルが存在します。
touchコマンドでファイルを作成し、条件式でファイルが存在していればメッセージを出力しています。$ WORD="Hello World"
$ [[ ${WORD} == Hello* ]] && echo True || echo False
True
条件式でパターンマッチングを行う例です。$ DATETIME=$(date "+%Y/%m/%d %H:%M:%S"); echo ${DATETIME}
2022/03/13 18:09:35
$ [[ ${DATETIME} =~ ^([0-9]{4})\/([0-9]{2})\/([0-9]{2})\ ([0-9]{2}):([0-9]{2}):([0-9]{2})$ ]]
$ echo ${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}
2022-03-13
$ echo ${BASH_REMATCH[4]}:${BASH_REMATCH[5]}:${BASH_REMATCH[6]}
18:09:35
拡張正規表現を使ったパターンマッチングの例となります。$ [[ $(diff -q file1 file2>/dev/null)$? -eq 1 ]] && cp -f file1 file2
$(コマンド)$?というコマンド置換の終了ステータスに展開される例です。
|
この例ではブレース展開を使って0から9までの数字を単語として展開されるため、10回分の繰り返し(0から9まで)となります。 |
|
位置パラメータが単語としてパラメータ展開されるため、位置パラメータの数だけ繰り返しとなります。 |
下記のスクリプトmod.shを作成して確認します。
|
コマンド置換によってコマンドの標準出力が単語として展開されます。 この例ではlsコマンドの標準出力、カレントディレクトリのファイル名が展開されます。 それぞれのファイルに対して所有者の権限を確認しています。 |
$ for ((i=0; i<=9; i++)); do echo $i; done
0
1
2
3
4
5
6
7
8
9
この例では0から9まで繰り返す例です。$ set -- apple orange banana grape
$ for ((i=1; i<=$#; i++)); do eval echo '\$'$i: \$$(($i)); done
$1: apple
$2: orange
$3: banana
$4: grape
位置パラメータの数だけ繰り返す例です。$ for ((end=$(date --date "+1 mins" +%s); $(date +%s)<$end;)) ; do date; sleep 10; done
2022年 3月 13日 日曜日 19:01:01 JST
2022年 3月 13日 日曜日 19:01:11 JST
2022年 3月 13日 日曜日 19:01:21 JST
2022年 3月 13日 日曜日 19:01:31 JST
2022年 3月 13日 日曜日 19:01:41 JST
2022年 3月 13日 日曜日 19:01:51 JST
現在の時間から一定時間後まで処理を繰り返す例です。#!/usr/bin/bash
PS3="fruilt?: "
select fruit in apple orange banana exit;
do
if [[ -n ${fruit} ]]; then
echo "${fruit}が選択されました。";
if [[ ${fruit} == "exit" ]] ; then
echo "終了します。"
exit
elif [[ ${fruit} == "apple" ]] ; then
price=380
elif [[ ${fruit} == "orange" ]] ; then
price=350
elif [[ ${fruit} == "banana" ]] ; then
price=300
fi
echo "${fruit}の価格は${price}です。"
else
echo "${REPLY}は正しくありません。" 1>&2
echo "正しい値を入力してください。" 1>&2
fi
done
|
inに続く単語に番号が付加され、一覧として標準エラー出力に出力されます。 続けて入力を促すプロンプトとしてPS3に設定された文字列が標準エラー出力に出力されます。 1を入力すると対応する単語appleがselectに続けて指定された変数fruitに代入されます。 読み込まれた行はREPLYにも代入されます。 ifによって処理が分岐され、${fruit} == "apple"が成立するため、thenに続くprice=380が実行されます。 echoコマンドによって選択された${fruit}とその${price}が標準出力に出力されます。 再びPS3をプロンプトとして出力して入力を待ちます。 |
|
最初にデータファイルdataを作成します。 ここではechoコマンドによって3と1を1行ずつリダイレクションして書き込んでいます。 作成したデータファイルをリダイレクションを使ってselect.shの入力としています。 1行ずつデータが読み込まれ、それぞれ3と1に対応する単語bananaとappleが変数fruitに代入されます。 読み込まれた行はREPLYにも代入されます。 ifによって処理が分岐され、${fruit} == "banana"と${fruit} == "apple"が成立するため、thenに続くprice=300とprice=380がそれぞれ実行されます。 echoコマンドによって選択された${fruit}とその${price}が標準出力に出力されます。 データファイルの読み込みが終端まで到達したためEOFとなり、selectコマンドは終了します。 |
|
PS3をプロンプトの出力後、Ctrl+Dを入力するとEOFと見做され、selectコマンドは終了します。 |
|
4(exit)を入力した場合、${fruit} == "exit"が成立するため、メッセージを出力してスクリプトを終了しています。 |
演算子 | 説明 |
---|---|
;; | 最初にマッチしたパターンに対応するリストのみが実行されます。 |
;& | マッチしたパターンに対応するリストと次に続くパターンに対応するリストが実行されます。 この時、次に続くパターンにマッチしていなくても対応するリストが実行されます。 |
;;& | マッチしたパターンに対応するリストが実行され、引き続き後続のパターンの評価が続けられます。 他にマッチしたパターンがあれば対応するリストが実行されます。 |
#!/usr/bin/bash
while :
do
echo "文字を入力してください"
read var
case ${var} in
( 1|2 )
echo ${var}が入力されました;&
( [0-9] )
echo 数字が入力されました;;
( a* )
echo 'a*'が入力されました;;&
( abc* )
echo 'abc*'が入力されました;;&
( abcd )
echo abcdが入力されました;;
( exit )
echo "終了します"; exit ;;
esac
done
|
入力された「1」は最初のパターン「1|2」にマッチするため、対応するechoが実行されます。 演算子が「;&」であるため、次に続くパターンに対応するechoも無条件で実行され、その演算子が「;;」であるため、caseコマンドの実行は終了します。 |
|
入力された「3」はパターン「[0-9]」にマッチするため、対応するechoが実行されます。 演算子が「;;」であるため、caseコマンドの実行は終了します。 |
|
入力された「a」はパターン「a*」にマッチするため、対応するechoが実行されます。 演算子が「;;&」であるため、他のパターンの評価が継続されますが、他にマッチするパターンがないため、caseコマンドの実行は終了します。 |
|
入力された「abcd」はパターン「a*」にマッチするため、対応するechoが実行されます。 演算子が「;;&」であるため、他のパターンの評価が継続され、パターン「abc*」にマッチするため、対応するechoが実行されます。 その演算子も「;;&」であるため、他のパターンの評価が継続され、パターン「abcd」にもマッチするため、対応するechoが実行されます。 この演算子は「;;」であるため、caseコマンドの実行は終了します。 |
|
入力された「abcde」はパターン「a*」にマッチするため、対応するechoが実行されます。 演算子が「;;&」であるため、他のパターンの評価が継続され、パターン「abc*」にマッチするため、対応するechoが実行されます。 その演算子も「;;&」であるため、他のパターンの評価が継続されますが、他にマッチするパターンがないため、caseコマンドの実行は終了します。 |
|
入力された「exit」はパターン「exit」にマッチするため、対応するechoとexitが実行され、スクリプトが終了します。 |
$ i=0; while : ; do if [[ $i -gt 9 ]]; then break; fi; echo $((i++)); done
0
1
2
3
4
5
6
7
8
9
はじめに変数iの値に0を代入しています。$ i=0; while [[ $i -le 9 ]] ; do echo $((i++)); done
0
1
2
3
4
5
6
7
8
9
はじめに変数iの値に0を代入しています。$ i=0; until [[ $i -gt 9 ]] ; do echo $((i++)); done
0
1
2
3
4
5
6
7
8
9
上記whileの例をuntilに置き換えた例です。
シェルは複合コマンドを関数として定義することができます。関数は一連のコマンドを名前を付けて保存したものと言えます。
関数名 () 複合コマンド [リダイレクション]
または
function 関数名 [()] 複合コマンド [リダイレクション]
関数は上記のいずれかの記述で定義することができます。予約語functionが記述された場合、関数名の後の()は省略することができます。
一般的に関数は{}に囲まれたリストを記述しますが、複合コマンドであればどの記述も可能です。
関数の定義でリダイレクションが指定された場合、関数が実行されるたびにリダイレクションが行われます。
関数の定義の終了ステータスは同じ名前の関数が読み込み専用で定義されているか文法エラーがある場合、0以外となりますが、正常に関数が定義できた場合は0を返します。
関数を実行した時の終了ステータスは、関数内で最後に実行されたコマンドの終了ステータスとなります。
関数内でreturnに引き数を指定して任意の終了ステータスを呼び出し元に返すことができます。
exportに-fオプションを指定して実行すると、関数を実行環境にエクスポートすることができます。エクスポートされた関数は後続のサブシェル内でも実行することができます。
unsetに-fオプションを指定して実行すると、関数定義を削除することができます。
declareに-fオプションを指定して実行すると、関数の名前と定義を標準出力に出力します。-Fオプションを指定して実行すると、関数名だけが標準出力に出力されます。extdebugが有効化されていれば、-Fオプションと関数名を指定して実行するとその関数が定義されているソースファイルの名前と行番号が標準出力に出力されます。
定義された関数は単純なコマンドとして現在のシェルで実行することができ、サブシェルは生成されません。
また、実行時に指定された引き数を関数内では新しい位置パラメータとして参照することができます。指定された引き数の数に合わせて特殊パラメータの$#も更新されます。$0は更新されませんが、FUNCNAMEの最初の要素(${FUNCNAME[0]})に実行中の関数名が設定されます。
DEBUGとRETURNのトラップは関数にtrace属性が与えられている場合とfunctraceが有効化されている場合を除いて継承されません。
ERRのトラップはerrtraceが有効化されている場合を除いて継承されません。
関数内でreturnを実行すると、その関数の実行は終了し、RETURNのトラップに設定されたコマンドが実行されます。その後、関数の呼び出し元に戻って次のコマンドから実行が再開されます。
呼び出し元に戻る時に位置パラメータと特殊パラメータの$#は関数を呼び出した時の状態に復元されます。
localで変数を宣言することで、関数内(とその関数から呼ばれる別の関数を含む)でローカルな変数を定義することができます。
関数は自身を再帰的に呼び出すことができます。デフォルトでは再帰的な呼び出しの深さに制限はありません。
FUNCNEST変数に0より大きな値を設定すると、その値を超えた深さの関数の呼び出し(再帰呼び出し以外の別の関数の呼び出しも含む)は失敗します。
上記以外は、関数内の実行環境は、呼び出したシェルの実行環境と同じとなります。
シェルはエイリアスとして事前に登録された単語がコマンドの読み込み時に単純なコマンドの先頭の単語として現れると別の文字列に置換することができます。
これをエイリアスと言い、aliasで登録、unaliasで削除することができます。
alias [-p] [エイリアス名[=置換する文字列] ...]
aliasコマンドを引き数を指定せずに実行するか、-pオプションを指定して実行すると、現在の実行環境に登録されている全てのエイリアスのリストが「alias エイリアス名=置換文字列」の形式で標準出力に出力されます。
置換文字列が指定されていない(エイリアス名だけの)引き数が指定された場合、そのエイリアス名で登録されているエイリアスが「alias エイリアス名=置換文字列」の形式で標準出力に出力され、真の値を返します。
置換文字列が指定されている引き数が指定された場合、現在の実行環境に登録します。
エイリアスの名前には、/、$、`、=、\、'、"、およびメタ文字は使用できませんが、置換される文字列には、メタ文字も含めてシェルの入力で記述できる文字は全て使用できます。
シェルはコマンドを解釈して実行する際、各コマンドの最初の単語がクォートされていない場合、その単語がエイリアスとして登録されているかどうか確認し、事前にエイリアスとして登録されていれば登録されている文字列に置換されます。
置換された文字列の先頭の単語に対してもエイリアスかどうか評価が行われますが、置換された文字列の先頭の単語がそのエイリアスの名前と同じ場合には再帰的に置換されることはありません。
例えば、"ls -F"という文字列をlsという名前でエイリアス登録した場合、置換されたlsが"ls -F"として再び置換されることはありません。
エイリアスに登録されている置換文字列の最後の文字が空白文字の場合、エイリアスが展開された時、空白文字に続く次の単語に対してもエイリアスかどうかが評価されます。
エイリアスで置換される文字列に引き数を含んで置換時に評価させることはできません。
引き数を渡す必要がある場合は関数定義を使用してください。
シェルが対話型でない場合、expand_aliasesが有効化されていない限り、エイリアスの置換は行われません。
シェルが対話型の場合でもexpand_aliasesが無効化されると、エイリアスの置換は行われなくなります。
エイリアスの置換はコマンドの読み込み時に行われます。
このため、エイリアスの登録と置換を同じコマンド行内で行うことはできません。エイリアスは実行環境に登録を完了させてから置換することが可能となります。
これは、関数定義の中でエイリアスを行う場合も同様です。独立した行でエイリアスの登録が実行されない限り、エイリアスが置換されることはありません。
実行例:
$ alias ll='ls -l'
$ ll /usr
合計 300
dr-xr-xr-x. 2 root root 69632 4月 11 11:31 bin
drwxr-xr-x. 2 root root 4096 4月 11 2018 etc
drwxr-xr-x. 2 root root 4096 4月 11 2018 games
drwxr-xr-x. 114 root root 12288 2月 27 17:17 include
dr-xr-xr-x. 61 root root 4096 2月 27 17:48 lib
dr-xr-xr-x. 208 root root 159744 3月 27 00:41 lib64
drwxr-xr-x. 60 root root 12288 2月 13 15:55 libexec
drwxr-xr-x. 18 root root 4096 5月 6 2020 local
dr-xr-xr-x. 2 root root 20480 3月 5 15:17 sbin
drwxr-xr-x. 328 root root 12288 2月 27 17:48 share
drwxr-xr-x. 5 root root 4096 2月 27 17:48 src
lrwxrwxrwx. 1 root root 10 11月 23 2018 tmp -> ../var/tmp
$ alias hello='echo Hello World'
$ hello
Hello World
シェルが対話的に実行されていてシェルのオプションのinteractive_commentsが有効化(デフォルトで有効化)されているか、非対話で実行(例えば、スクリプトなど)されている場合、# で始まる単語があると、その単語から行末まではコメントと見做され、全て無視されます。
bashを含むコマンドを実行する際、コマンド名に続けて指定される一連の単語を引き数と言います。
引き数のうち、-や+(または--)で始まる単語でコマンドの振舞いや属性を指定するものをオプションと言い、単一の単語で構成されるものとオプションに続く単語と合わせて構成されるものがあります。
シェルの起動時に下記の属性を設定したり、set、shoptで実行中のシェルの属性を変更することができます。
bashとsetはオプションの前に[-+]がある場合、-を付加するとそのオプションが有効となり、+を付加するとそのオプションが無効となります。
設定方法:
bash | set | shopt | オプションの動作(属性) | |
---|---|---|---|---|
[-+]a または [-+]o allexport | [-su] -o allexport | 新規に設定される変数、および値が変更される変数と関数が自動的にエクスポートされます。 | ||
[-+]b または [-+]o notify | [-su] -o notify | ジョブの終了ステータス、およびジョブの状態変化を次のプライマリプロンプトの出力時ではなく、即座に出力します。 | ||
[-+]e または [-+]o errexit | [-su] -o errexit | 単純なコマンド、パイプライン、()に囲まれたリスト、{}に囲まれたリストで実行される1つのコマンドが0以外の終了ステータスで終了した場合、後続の処理を中止し即座にシェルを終了します。 ただし、以下の場合はシェルは終了せずに後続の処理を継続します。
このオプションはシェルの実行環境ごとに適用されるため、現在のシェルとサブシェルでは別々に適用されます。それぞれのシェルの実行環境ごとにオプションを適用する必要があります。 | ||
[-+]f または [-+]o noglob | [-su] -o noglob | パス名展開を無効にします。 | ||
[-+]h または [-+]o hashall | [-su] -o hashall | ハッシュテーブルを有効化し、組み込みコマンド以外のコマンドをハッシュテーブルに記憶できるようにします。 これにより外部コマンドをPATHから検索するのではなく、ハッシュテーブルから高速に実行できるようにすることができます。 このオプションはデフォルトで有効化されています。 ハッシュテーブルの操作はhashで行うことができます。 | ||
[-+]k または [-+]o keyword | [-su] -o keyword | コマンド名の前にある代入文だけでなく、引き数として指定された全ての代入文をそのコマンドの環境変数として追加します。 以下のスクリプトkeyword.shを作成して確認します。
このオプションを有効化する前はコマンド名の前に記述された代入文だけが環境変数として設定され、スクリプト内で参照できます。このオプションを有効化した後では引き数として記述された代入文も環境変数として設定され、スクリプト内で参照できるようになります。 | ||
[-+]m または [-+]o monitor | [-su] -o monitor | ジョブ制御を有効化し、バックグラウンドプロセスとその終了ステータスがプロセスの終了時に表示されます。 ジョブ制御をサポートしているシステムではデフォルトで有効化されます。 | ||
[-+]n または [-+]o noexec | [-su] -o noexec | コマンドを読み込んで実行をせずにスクリプトの文法チェックのみ行います。 対話型のシェルでは無視されます。 | ||
[-+]o emacs | [-su] -o emacs | コマンド行の編集にemacs形式のインタフェースを使用します。 対話型のシェルではデフォルトで有効化されています。ただし、noedtingオプションが有効かされている場合を除きます。 read -eでの編集インタフェースにも影響します。 | ||
[-+]o history | [-su] -o history | コマンド履歴を有効化します。 対話型のシェルではデフォルトで有効されています。 | ||
[-+]o ignoreeof | [-su] -o ignoreeof | 「IGNOREEOF=10」コマンドを実行した場合と同じ効果を持ち、行頭でEOF(<Ctl>-d)が10回続けて入力されても無視します。 それ以上のEOFが行頭で入力された場合、シェルを終了します。 | ||
[-+]o pipefail | [-su] -o pipefail | パイプライン中のコマンドで0以外の終了ステータスを返した最も後段(右側)のコマンドの終了ステータスが返されます。 パイプラインの全てのコマンドが成功の状態で終了すると0が返されます。 | ||
--posix | [-su] -o posix | bashの動作がPOSIX標準と異る部分をPOSIX準拠となるように変更します。 | ||
[-+]o posix | ||||
[-+]o vi | [-su] -o vi | コマンド行の編集にvi形式のインタフェースを使用します。 read -eでの編集インタフェースにも影響します。 | ||
-o | -oに続けてオプション名を指定しなかった場合、現在有効化されているオプションが出力されます。 | |||
+o | -oに続けてオプション名を指定しなかった場合、現在のオプション設定を再生成するsetコマンドが出力されます。 | |||
[-+]p または [-+]o privileged | [-su] -o privileged | 特権モードを有効化します。 bash起動時にこのオプションが指定された場合、ENV、BASH_ENV、SHELLOPTS、BASHOPTSは無視され、シェル関数も継承されません。 また、このオプションが有効化されている場合、CDPATH、GLOBIGNORE環境変数は無視されます。 実ユーザー(グループ)IDと異る実効ユーザー(グループ)IDでシェルが起動された時、同時にこのオプションが指定されている場合、シェルは異る実効ユーザー(グループ)IDで起動されます。このオプションが指定されていない場合、実ユーザー(グループ)IDで起動されます。 実ユーザー(グループ)IDと異る実効ユーザー(グループ)IDでシェルが起動された後、このオプションを無効化すると実効ユーザーIDと実効グループIDは実ユーザーIDと実グループIDに設定されます。 | ||
[-+]t または [-+]o onecmd | [-su] -o onecmd | bashの起動時に指定された場合、コマンド行を1行だけ読み込んで実行してすぐに終了します。 setまたは、shoptから設定された場合、即座にそのシェルが終了します。 | ||
[-+]u または [-+]o nounset | [-su] -o nounset | パラメータ展開を行う時、特殊パラメータの「$@」または、「$*」以外の未設定のパラメータを展開しようとするとエラーを発生させます。 シェルが対話型でなければ、0以外の終了ステータスでシェルが終了します。 | ||
--verbose | [-su] -o verbose | シェルが入力行を読み込んだ時、読み込んだコマンド行を標準エラー出力に出力します。 | ||
[-+]v または [-+]o verbose | ||||
[-+]x または [-+]o xtrace | [-su] -o xtrace | 単純なコマンド、forコマンド、caseコマンド、selectコマンド、算術forコマンドをそれぞれ展開した後、PS4を展開した値を表示し、その後にそのコマンドと展開した引き数、単語のリストを標準エラー出力に出力します。 スクリプトの実行時に展開した値を含んだトレースを行えるためデバッグに使用できます。 | ||
[-+]B または [-+]o braceexpand | [-su] -o braceexpand | ブレース展開を有効化します。 このオプションはデフォルトで有効化されています。 このオプションを無効化することでブレース展開を抑止できます。 | ||
[-+]C または [-+]o noclobber | [-su] -o noclobber | リダイレクション演算子>、>&、<>を使った上書きを禁止します。このオプションを有効化した場合、>|を使用する時のみ上書きができるようになります。 >>による追記は可能です。 実行例:
| ||
[-+]E または [-+]o errtrace | [-su] -o errtrace | ERRのトラップを関数、コマンド置換、サブシェルで実行されるコマンドに継承します。 ERRのトラップは単純なコマンド、パイプライン、()に囲まれたリスト、{}に囲まれたリストで実行される1つのコマンドが0以外の終了ステータスで終了した場合にtrapによってERRに設定されているコマンドを実行します。ただし、以下の場合を除きます。
| ||
[-+]H または [-+]o histexpand | [-su] -o histexpand | !を使った履歴置換を有効化します。 シェルが対話型の場合、このオプションはデフォルトで有効化されています。 | ||
[-+]P または [-+]o physical | [-su] -o physical | cdやpushdでカレントディレクトリを変更する先がシンボリックリンクの場合、論理ディレクトリではなく、リンク先の物理ディレクトリに移動します。 このオプションが有効化されていない場合、論理ディレクトリへ移動します。 実行例:
| ||
[-+]T または [-+]o functrace | [-su] -o functrace | DEBUGとRETURNのトラップを関数、コマンド置換、サブシェルで実行されるコマンドに継承します。 DEBUGのトラップは単純なコマンド、forコマンド、caseコマンド、selectコマンド、算術forコマンドの前、および関数内の最初のコマンドの実行前にtrapによってDEBUGに設定されているコマンドを実行します。 RETURNのトラップは関数の終了、.、およびsourceで読み込んだスクリプトが終了した場合にtrapによってRETURNに設定されているコマンドを実行します。 実行例はトレース情報の出力(DEBUGのトラップ)を参照してください。 | ||
-- | オプションの終わりを明示的に指定するために使用します。 bash起動時にこのオプションが指定された場合、これ以降の引き数は全てファイル名や引き数として処理されます。 setではこれ以降に引き数が指定されていない場合、現在のシェルの位置パラメータが取り消され、これ以降に引き数が指定されている場合、現在のシェルの位置パラメータがその内容(これ以降の引き数)に置換されます。 | |||
- | オプションの終わりを明示的に指定するために使用します。 bash起動時にこのオプションが指定された場合、--と同じとなります。 setではこれ以降の引き数がある場合、現在のシェルの位置パラメータがその内容(これ以降の引き数)に置換されます。これ以降に引き数がない場合は位置パラメータの内容は変化しません。また、-xと-vオプションは無効となります。 | |||
-c 文字列 | 文字列はbashが実行するコマンド行と$0から始まる位置パラメータして解釈されます。 bashを-cオプションを指定して実行すると以下のようにそれぞれのサブシェルが起動されます。 実行例:
サブシェルとしてbashが起動されそのbashの位置パラメータが指定された引き数に設定されています。$0: コマンド名 $1: 1 $2: 3 $3: 3 このため、echoを実行するとその位置パラメータを表示しています。
この例ではダブルクォートでクォートされているため、コマンド行の処理時に$0,$1,$2,$3が展開されてしまいます。その結果、上記例は以下を実行したことと同じになります。 $ bash -c echo /usr/bin/bash,,, コマンド名 1 2 3 ここで"/usr/bin/bash,,, コマンド名 1 2 3"がechoの結果として出力されないことに疑問を持たれるかも知れません。 これは-cオプションの最初の引き数である「echo」はコマンドとして解釈されていますが、それ以降の文字列は「echo」に対する引き数ではなく、現在のシェルからサブシェルとして起動された「bash」の位置パラメータとして展開されているためです。 下記のスクリプトtest.shを作成して同様に確認します。
実行例:
上記「echo」の例で示した時のようにtest.shに続く文字列はそのスクリプトの引き数ではなく、サブシェルとして起動されたbashの位置パラメータに設定されてしまっているため、$0もスクリプト名のままとなり、引き数もありません。
この例では.コマンドを使ってサブシェルとして起動したbashでスクリプトを読み込んで実行させています。このため、スクリプト内で$0を参照するとコマンドに続けて指定された"aaa"が展開され、位置パラメータに"bbb"と"ccc"も展開されています。
この例ではスクリプトに引き数を直接与えているため、サブシェルであるbashの$0を含む位置パラメータは指定された文字列となりますが、スクリプトに渡される引き数はzzzのみとなります。このように-cで複数の文字列を指定した場合、$0を任意の文字列に書き換えることが可能です。 スクリプト内で$0の値によって処理を変更するなどの応用が考えられます。 | |||
-i | 対話型のシェルとしてbashを動作させます。 | |||
--login または -l | ログインシェルとして起動されたかのようにbashを動作させます。 | |||
--restricted または -r | 制限付きのシェルとしてbashを動作させます。 rbashという名前でシェルが起動された場合、このオプションが指定されたことと等価となります。 制限付きのシェルは以下について実行が制限(許可されない、実行されない)されます。
| |||
-s | このオプションが指定された場合、オプションとして認識できない文字列は対話型のシェルを起動する際の位置パラメータとして扱われます。 例えばbash -s test.shとした場合、test.shをスクリプトとして読み込むのではなく、対話型のシェルが起動し、位置パラメータ$1にtest.shが設定されます。 | |||
--dump-strings または -D | このオプションが指定されると自動的に-nオプションも指定されたことになり、スクリプトの実行は行われず、スクリプト中のローカライズ対象の文字列($"文字列")を抽出して標準出力に出力します。 例として下記のようなスクリプトlocal.shを作成します。
実行例:
ローカライズの手順についてはLC_MESSAGESを参照してください。 | |||
--dump-po-strings | --dump-stringsと同じですが、GNUのgettextのpoファイル形式の出力となります。 実行例:
| |||
--help | bashの起動のコマンド行についてのメッセージを標準出力に出力します。 | |||
--init-file <file> または --rcfile <file> | 対話型シェルの起動時にこのオプションが指定された場合、~/.bashrcの代わりにfileを設定ファイルとして実行します。 | |||
--noediting | 対話型のシェルの場合、コマンド行を読み込む際にGNU readlineライブラリを使用しません。readlineライブラリは補完などの機能を提供しているため、このオプションが指定された場合、それらの機能が使えなくなります。 | |||
--noprofile | シェルの起動時にこのオプションが指定された場合、設定ファイル/etc/profile、~/.profile、~/.bash_profile、~/.bash_loginのいずれも読み込みません。 | |||
--norc | 対話型のシェルの起動時にこのオプションが指定された場合、~/.bashrcを読み込みません。 shという名前でシェルが起動された場合、このオプションが指定されたことと等価となります。 | |||
--version | bashのバージョン情報を標準出力に出力します。 | |||
[-+]O autocd | [-su] autocd | 対話型のシェルでディレクトリ名をコマンドとして入力した場合、cdの引き数にディレクトリ名が指定されたものとしてカレントディレクトリを変更します。 実行例:
| ||
[-+]O cdable_vars | [-su] cdable_vars | cdの引き数にディレクトリ名でない文字列が指定された場合、その文字列を変数名と見做して、その値のディレクトリにカレントディレクトリを変更します。 実行例:
| ||
[-+]O cdspell | [-su] cdspell | 対話型のシェルでcdの引き数に指定されたディレクトリ名のタイプミスを自動的に訂正するよう試みます。訂正される誤りは文字の入れ替わり、文字の不足、冗長な文字の指定です。 訂正が行われた場合、訂正後のディレクトリ名が表示されカレントディレクトリを変更します。 | ||
[-+]O checkhash | [-su] checkhash | ハッシュテーブルが有効化されている場合で、かつ実行しようとするコマンドがハッシュテーブルに見つかった場合、コマンドを実行する前に実際にそのコマンドが存在するかどうかチェックします。 コマンドが存在しない場合、PATHから検索します。 ハッシュテーブルにコマンドがフルパスで記憶されていて、存在しなかった場合、ハッシュテーブルから削除されます。 ハッシュテーブルにコマンドが相対パスで記憶されていて、存在しなかった場合、ハッシュテーブルからは削除されません。 ハッシュテーブルに記憶されているパスにコマンドが存在せず、相対パスを除く他のパスで見つかった場合、ハッシュテーブルが更新されます。 | ||
[-+]O checkjobs | [-su] checkjobs | 対話型のシェルを終了する前に停止中のジョブや実行中のジョブがないか確認します。 停止中のジョブや実行中のジョブがあればそれらのジョブの一覧を表示し、シェルの終了を待ちます。他のコマンドの実行を挟まずにもう一度続けてシェルの終了が試みられた場合、シェルを終了します。 実行例:
| ||
[-+]O checkwinsize | [-su] checkwinsize | コマンドの実行後に毎回ウィンドウの大きさをチェックし、LINESとCOLUMNSの値を更新します。 | ||
[-+]O cmdhist | [-su] cmdhist | 複数行にわたるコマンドを同一の履歴エントリに保存できるようにします。この際、文法的な正しさを保つためにセミコロンが必要に応じて付加されます。 このオプションはデフォルトで有効化されています。 このオプションが無効化されると複数行にわたるコマンドはそれぞれの行ごとに履歴エントリに保存されます。 実行例:
| ||
[-+]O compat31 | [-su] compat31 | bash version 3.1の動作と互換性を保つように以下の5つの動作を変更します。
| ||
[-+]O compat32 | [-su] compat32 | bash version 3.2の動作と互換性を保つように以下の4つの動作を変更します。
| ||
[-+]O compat40 | [-su] compat40 | bash version 4.0の動作と互換性を保つように以下の3つの動作を変更します。
| ||
[-+]O compat41 | [-su] compat41 | bash version 4.1の動作と互換性を保つように以下の2つの動作を変更します。
| ||
[-+]O direxpand | [-su] dirspell | 2つのオプションを同時に有効化することで指定されたディレクトリがスペルミスなどで見つからなかった場合、補完のときに正しいパスに修正され、フルパスに置換されます。 実行例:
| ||
[-+]O dirspell | [-su] dirspell | |||
[-+]O dotglob | [-su] dotglob | パス名展開に.で始まるファイル名を含めます。 GLOBIGNOREに空文字列以外が設定された場合、このオプションが有効化されます。 | ||
[-+]O execfail | [-su] execfail | 対話型ではないシェルでexecへの引き数として指定されたコマンドの実行に失敗した場合、シェルを終了せず継続します。 このオプションが有効化されていない場合、対話型ではないシェルでexecへの引き数として指定されたコマンドの実行に失敗するとシェルは終了します。 対話型のシェルはexecへの引き数として指定されたコマンドの実行に失敗してもシェルは終了せず継続します。 | ||
[-+]O expand_aliases | [-su] expand_aliases | エイリアスが有効化されます。 対話型のシェルではデフォルトで有効化されています。 実行例:
| ||
--debugger または [-+]O extdebug | [-su] extdebug | 拡張デバッグモード(以下のデバッグのための動作)が有効化されます。
| ||
[-+]O extglob | [-su] extglob | パス名展開の拡張パターンマッチングが有効化されます。 | ||
[-+]O extquote | [-su] extquote | パラメータがダブルクォートで囲まれている場合、${パラメータ名}の展開で$'文字列'または、$"文字列"のクォートを展開します。 このオプションはデフォルトで有効化されています。 実行例:
| ||
[-+]O failglob | [-su] failglob | パス名展開でパターンにマッチするファイルが存在しない場合、エラーメッセージが表示されコマンドの実行は失敗します。 | ||
[-+]O force_fignore | [-su] force_fignore | FIGNOREに設定されているファイルのサフィックスにマッチするファイルはすべて例外なく補完候補から除外されます。 このオプションが有効化されていない場合、除外されたファイルが唯一の補完候補である場合、除外されずに補完されます。 このオプションはデフォルトで有効化されています。 | ||
[-+]O globstar | [-su] globstar | パス名展開でパターンに**が指定された場合、サブディレクトリを再帰的に探索し、すべてのディレクトリ、サブディレクトリとファイルにマッチします。**/が指定された場合、サブディレクトリを再帰的に探索し、すべてのディレクトリとサブディレクトリにマッチします。 | ||
[-+]O gnu_errfmt | [-su] gnu_errfmt | シェルのエラーメッセージがGNU標準のエラーメッセージの形式で出力されます。 | ||
[-+]O histappend | [-su] histappend | シェルの終了時にHISTFILEで指定されているファイルにコマンドの履歴が追記されます。 このオプションが有効化されていない場合、コマンドの履歴は上書きされます。 | ||
[-+]O histreedit | [-su] histreedit | readlineが使用されている場合、履歴置換に失敗するとプロンプトに続いて入力した(失敗した)コマンドが表示され、再編集が可能となります。 このオプションが有効化されていない場合、履歴置換に失敗するとプロンプトが表示されて次のコマンドの入力を待ちます。 実行例:
| ||
[-+]O histverify | [-su] histverify | readlineが使用されている場合、履歴置換の結果はいったんreadlineの編集バッファに読み込まれます。コマンドを確認したり必要な編集を行ってからシェルで実行することができます。 | ||
[-+]O hostcomplete | [-su] hostcomplete | readlineが使用されている場合、@を含む単語を補完しようとすると、ホスト名として補完を行います。 | ||
[-+]O huponexit | [-su] huponexit | 対話型のログインシェルを終了するときに全てのジョブにSIGHUPを送信します。 | ||
[-+]O interactive_comments | [-su] interactive_comments | 対話型のシェルに#で始まる単語から行末までをコメントとして認識するようにします。 このオプションはデフォルトで有効化されています。 | ||
[-+]O lastpipe | [-su] lastpipe | ジョブ制御が有効でなければ、フォアグラウンドで実行されたパイプラインの最後のコマンドを現在のシェル環境で実行します。 実行例: set +mを実行することでmonitorオプションを無効化(ジョブ制御を無効化)しています。パイプラインの最後のSTR=Helloが現在のシェル環境で実行されるため、変数STRの値が書き換えられています。 | ||
[-+]O lithist | [-su] lithist | cmdhistとともに有効化された場合、複数行にわたるコマンドを同一の履歴エントリに保存する際、できる限り改行を埋め込むことで履歴を保存します。 実行例:
| ||
[-+]O login_shell | [-su] login_shell | シェルがログインシェルとして起動された場合、このオプションが有効化されます。 このオプションは変更することができません。 | ||
[-+]O mailwarn | [-su] mailwarn | bashがメールのチェックに使うファイルが前回のチェック以降にアクセスされている場合、メッセージ「The mail in メールファイル has been read"が表示されます。 | ||
[-+]O no_empty_cmd_completion | [-su] no_empty_cmd_completion | readlineが使用されている場合、空行で補完を行おうとしてもPATHからコマンドを検索しません。 | ||
[-+]O nocaseglob | [-su] nocaseglob | パス名展開のパターンマッチングで英大文字と英小文字の区別をしません。 | ||
[-+]O nocasematch | [-su] nocasematch | caseや[[ 式 ]]のパターンマッチングで英大文字と英小文字の区別をしません。 | ||
[-+]O nullglob | [-su] nullglob | パス名展開のパターンマッチングでパターンにマッチするファイルが存在しない場合、指定されたパターンは削除され、空文字列が展開されます。 | ||
[-+]O progcomp | [-su] progcomp | プログラム補完機能が有効化されます。 このオプションはデフォルトで有効化されています。 | ||
[-+]O promptvars | [-su] promptvars | プロンプト文字列に対して、バックスラッシュでエスケープされた特殊文字が展開された後、パラメータ展開、コマンド置換、算術式展開、クォートの削除が行われます。 このオプションはデフォルトで有効化されています。 | ||
[-+]O restricted_shell | [-su] restricted_shell | シェルが制限付きのシェルとして起動された場合、このオプションが有効化されます。 このオプションは変更することができません。 | ||
[-+]O shift_verbose | [-su] shift_verbose | shiftが位置パラメータの数を超えて呼び出された場合、エラーメッセージが出力されます。 | ||
[-+]O sourcepath | [-su] sourcepath | .、およびsourceが引き数として与えられたファイルをPATHから検索します。 このオプションはデフォルトで有効化されています。 | ||
[-+]O xpg_echo | [-su] xpg_echo | 組込コマンドのechoがバックスラッシュによるエスケープシーケンスを展開するようにします。 |
コマンドが単語に分割された後に単純なコマンドとその引き数(引き数は省略可能)となった場合、以下のようにコマンドが実行されます。
コマンド名に/が含まれてない場合、シェルは実行すべきコマンドの位置を特定しようとします。
コマンド名と同じ名前の関数定義が行われていれば、その関数を呼び出します。
関数定義に一致するものがなければ、組み込みコマンドのリストを検索し、一致するものがあれば、その組み込みコマンドを実行します。
関数定義も組み込みコマンドも一致するものがなく、コマンド名に/が含まれない場合、bashはPATHの各要素を順に検索(bashはハッシュ表を使って実行ファイルの完全なパス名を記憶します。ハッシュ表に一致するものがない場合のみ、PATHの各要素を検索します。)し、そのコマンド名に一致する実行ファイルを探します。
PATHから一致するコマンドを見つけられなかった場合、command_not_found_handleという名前の関数定義を検索し、その関数定義が存在すれば、元のコマンド名とその引き数を引き数としてcommand_not_found_handleを呼び出します。この関数の終了ステータスが返されます。
この関数定義が存在しない場合、エラーメッセージを標準エラー出力に出力して、終了ステータスとして127を返します。
PATH(およびハッシュ表)からの検索に成功するか、コマンド名に/が含まれる場合には、シェルは見つかった実行ファイルを外部コマンドとして、独立した実行環境で実行します。その実行環境の引き数 0には、コマンド名が設定され、引き数が指定されていれば、引き数がコマンドに受け渡されます。
見つかったファイルが実行ファイルでもディレクトリでもない場合、シェルはスクリプトと見做してそのファイルを読み込みます。
シェルはスクリプトを実行するためにサブシェルを起動して新しい実行環境でスクリプトを実行します。
スクリプトの最初の行が#!で始まる場合、その行の残りの文字列はスクリプトを実行するインタプリタとして見做され、シェルは指定されたインタプリタをOS上で実行します。
シェルは以下の要素からなる実行環境を持ちます。
組み込みコマンド、および関数は呼び出したそのシェルで実行されるため、独立した実行環境を持ちませんが、それ以外の単純なコマンド、コマンド置換、()に囲まれたリスト、コプロセス、制御演算子&をコマンドに付加した非同期コマンド、パイプラインの一部として起動された組み込みコマンドはサブシェルを起動するため、独立した実行環境を持ちます。
また、いくつかの要素は親から継承することができますが、親から継承したものであっても異る実行環境ではそれぞれ独立しているためサブシェル内での変更は影響しません。
|
|
シェルは実行中のプロセスを選択的に停止(サスペンド)させたり、後で実行を再開(レジューム)させたりすることができます。
bashが動作しているOSがジョブ制御をサポートしている場合、ユーザーはbashを使ってジョブの制御を行うことができます。
monitorを無効化することでジョブ制御を無効化することができます。
通常は対話型のインターフェースを通してこの機能を利用します。対話型のインターフェースはOSのカーネルの端末ドライバとbashの組み合わせで提供されます。
プロセスの動作中にサスペンド文字(通常は ^Z、Ctrl+Z)を入力すると、そのプロセスは停止させられ、bashに制御が戻ります。
遅延サスペンド文字(通常は ^Y、Ctrl+Y)を入力すると、そのプロセスが端末から読み込みを行おうとすると停止させられ、bashに制御が戻ります。
この時点でユーザーはこのジョブの状態を操作することができます。bgでバックグラウンドでの実行を継続させることができ、fgでフォアグラウンドで実行を継続させることができます。また、killでプロセスを強制終了させることもできます。
^Zの効果は即座に現れるため、未出力の出力や、先行入力した文字がある場合、破棄されます。
シェルはパイプラインごとに「ジョブ」を構成し、現在実行しているジョブの一覧を保持しています。
jobsでこの一覧をリスト表示することができます。
bashがジョブを非同期(バックグラウンド)に実行した時、bashは端末に以下のような行を出力します。
[1] 26721
これは、このジョブのジョブ番号が1で、このジョブを構成するパイプライン中の最後のプロセスのIDが26721であることを示しています。
1つのパイプラインに含まれる全てのプロセスは同一のジョブのメンバーです。bashは、ジョブ制御の基礎として、この「ジョブ」という抽象化機構を使用します。
ジョブの他にOSは「端末プロセスグループ」というグループの情報を管理しています。それぞれの端末プロセスグループには識別子として一意な端末プロセスグループIDというIDが割り振られています。
フォアグラウンドで実行されるプロセスは現在のシェルと同じ端末プロセスグループに所属し、バックグラウンドで実行されるプロセスは現在のシェルとは異る端末プロセスグループに所属します。
同じ端末プロセスグループに所属しているプロセスはキーボードで生成されたシグナルを等しく受信します。
このため、バックグラウンドで実行されるプロセスはキーボードで生成されたシグナルの影響を受けません。
フォアグラウンドのプロセスのみが端末から読み込むことができ、stty tostopで許可されている場合には、端末への出力を行うこともできます。
ジョブ制御が有効な状態でバックグラウンドのプロセスが端末から読み込みを行おうとすると端末ドライバからSIGTTINというシグナルが送信されます。stty tostopが有効な場合、バックグラウンドのプロセスが端末へ書き込みを行おうとするとSIGTTOUというシグナルが送信されます。このシグナルを補足しなければ、プロセスは停止します。
コマンド名を記述せずに、ジョブの名前だけを指定した場合、そのジョブをフォアグラウンドに移動させます。
つまり、fgが省略されたと見做されます。
例えば、%1はfg %1と同じで、ジョブ番号1のジョブをフォアグランドに移動します。
同様に%1 &はbg %1と同じで、ジョブ番号1のジョブをバックグラウンドで実行を再開させます。
ジョブの状態が変更されるとシェルはそれを即座に検知します。通常、bashがジョブの状態変化をユーザーに報告するのは、プロンプトを出力する直前となります。
これは、実行中の他の出力を妨害しないためです。
notifyが有効化されている場合、bashはジョブの状態の変化を即座に報告します。
子プロセスが終了する度に、SIGCHLDを受信します。
ジョブを停止させたままで(checkjobsオプションが有効化されている場合は実行中を含みます)bashを終了(exit)させようとすると、シェルは警告メッセージを出力します。checkjobsオプションが有効化されている場合は、ジョブとその状態を一覧表示します。この時、ジョブの状態を調べる場合には、jobsコマンドを使います。
警告メッセージの出力後、他のコマンドを実行せずにbashを再び終了させようとすると、シェルは警告を繰り返さずに、停止中のジョブを終了させます。
シェル上でジョブを指定するためには以下のような方法が使用できます。
指定 | 説明 |
---|---|
%n | ジョブ番号 nを指定します。 |
%% または %+ | シェルが記憶しているカレントジョブ(フォアグラウンドで実行中に停止させられたジョブ、またはバックグランドで起動された最後のジョブ)を指定します。 |
%- | カレントジョブの1つ前のジョブを指定します。 |
%文字列 | ジョブの名前が指定された文字列で始まるジョブを指定します。 複数のジョブ名に一致する場合、シェルはエラーを報告します。 |
%?文字列 | コマンド行中に指定された文字列を含むジョブを指定します。 複数のジョブ名に一致する場合、シェルはエラーを報告します。 |
|
|
シグナルはUnix系OSにおけるプロセス間の非同期なイベント通知機構です。シグナルを送信することによって送信先の(シグナルを受け取る)プロセスに対して非同期に割り込むことができます。
シグナルを受信する側のプロセスはシグナルのハンドラを登録することによって、特定のシグナルを受信した時に任意の処理を実行することができます。
シグナルのハンドルが登録されていない場合、デフォルトの動作が実行されます。
以下のようなデフォルトの動作があります。
シグナル名 | 番号(値) | デフォルトの動作 | 説明 | |
---|---|---|---|---|
SIGHUP | 1 | Term | ハングアップ | 端末の回線切断、クローズ時に送信。 |
SIGINT | 2 | Term | 割り込み | キーボードからの割り込み、通常はCtrl+Cの入力で送信。 |
SIGQUIT | 3 | Core | 終了とコアダンプ | キーボードからの中止、通常はCtrl+\の入力で送信。 |
SIGILL | 4 | Core | 不正な命令 | 不正な命令(例えば命令ではないメモリ領域へのジャンプ、特権を持たない状態で特権が必要な命令の実行など)を実行しようとした時に送信。 |
SIGABRT | 6 | Core | プロセスの中断 | abort(3)によって送信。 |
SIGFPE | 8 | Core | 浮動小数点例外 | 浮動小数点演算でゼロ除算やオーバーフローが発生した時に送信。 |
SIGKILL | 9 | Term | 強制終了 | killコマンドによる明示的な強制終了時に送信。 |
SIGSEGV | 11 | Core | セグメンテーション違反 | 不正なメモリを参照した時に送信。 |
SIGPIPE | 13 | Term | パイプの破壊 | 読み込む相手がいないパイプへの書き込み時に送信。 |
SIGALRM | 14 | Term | アラーム | alarm(2)によって設定したタイマーのタイムアウト時に送信。 |
SIGTERM | 15 | Term | 終了 | killコマンドのデフォルトのシグナル、killコマンドによる明示的な強制終了時に送信。 |
SIGUSR1 | 10 | Term | ユーザー定義シグナル1 | ユーザーによって定義されたシグナル。 Linuxではスレッド間の同期に使用されています。また、ddコマンドが受信すると進捗状況が表示されます。 |
SIGUSR2 | 12 | Term | ユーザー定義シグナル2 | ユーザーによって定義されたシグナル。 Linuxではスレッド間の同期に使用されています。 |
SIGCHLD | 17 | Ignore | 子プロセスの終了、停止 | 子プロセスの状態が変化した時に送信。 |
SIGCONT | 18 | Continue | 一時停止からの再開 | 一時停止中のプロセスの実行を再開させたい時に送信。 |
SIGSTOP | 19 | Stop | 一時停止 | プロセスの実行を一時停止させたい時に送信。 |
SIGTSTP | 20 | Stop | 端末からの一時停止 | フォアグラウンドのプロセスの実行を一時停止させたい時に送信。通常はCtrl+Zの入力で送信。 |
SIGTTIN | 21 | Stop | バックグラウンドプロセスの読み込み | バックグラウンドのプロセスが端末から読み込みを行おうとした時に送信。 |
SIGTTOU | 22 | Stop | バックグラウンドプロセスの書き込み | バックグラウンドのプロセスが端末へ書き込みを行おうとした時に送信。 |
シグナル名 | 番号(値) | デフォルトの動作 | 説明 | |
---|---|---|---|---|
SIGBUS | 7 | Core | バスエラー | 未定義のメモリ領域へのアクセス(アドレス境界を超えたアクセス、存在しない物理アドレスへのアクセスなど)時に送信。 |
SIGPOLL SIGIO | 29 | Term | ポーリング可能 | ファイルディスクリプタに対してポーリング可能(入出力が可能)な状態になった時に送信。 |
SIGPROF | 27 | Term | プロファイリングタイマー | プロファイリングのタイマーのタイムアウト時に送信。 |
SIGSYS | 31 | Core | 不正なシステムコール | システムコールの引き数が不正だった時に送信。 |
SIGTRAP | 5 | Core | トレース/ブレークポイントによるトラップ | デバッグ機能によって仕掛けたトラップへの到達時に送信。 |
SIGURG | 23 | Ignore | ソケット上の緊急データ | ソケット上のデータに緊急を示すフラグが立っているパケットの受信時に送信。 |
SIGVTALRM | 26 | Term | 仮想アラームクロック | 仮想時間をカウントするタイマーによって送信。 |
SIGXCPU | 24 | Core | CPU時間の制限 | プロセスのCPU使用時間が設定値を超えた時に送信。 |
SIGXFSZ | 25 | Core | ファイルサイズの制限 | ファイルサイズがファイルシステム、またはOSの制限値を超えた時に送信。 |