bash (Bourne-again shell) はUnixシェルのひとつである。sh (Bourne shell) に対して上位互換性があるため、shのスクリプトをそのまま実行することができる。ほとんどのLinuxディストリビューションにおいて、デフォルトのログインシェルとして採用されている。
$#
$-
$?
$$
$!
$*
$@
PS1
TMOUT
PPID
PWD
OLDPWD
UID
EUID
GROUPS
BASH
BASH_VERSION
SHLVL
RANDOM
HISTCMD
OPTARG
OPTIND
HOSTNAME
HOSTTYPE
OSTYPE
MACHTYPE
SHELLOPTS
BASH_ENV
HISTSIZE
HISTFILE
HISTFILESIZE
OPTERR
PROMPT_COMMAND
IGNOREEOF
FCEDIT
FIGNORE
GLOBIGNORE
HISTIGNORE
PIPESTATUS
HOME
PATH
CDPATH
MAIL
SHELL
LANG
LC_ALL
LC_COLLATE
LC_CTYPE
LC_MESSAGES
< filename
> filename
>> filename
<& fd
>& fd
<&-
>&-
/etc/profile
~/.bash_profile
~/.bash_login
~/.profile
シェルとは1つの実行プログラムであり、通常はログインシェルとして各ユーザがログインするたびに起動されて、そのプロセスはログアウトの際に消滅します。
ログインが行われるとホストは端末上に、例えば $ という表示を行っていますが、これがシェルが発している「プロンプト」(ユーザへのコマンドラインへの入力を促す記号です。
シェルには大きく分けて、コマンドインタープリタとしての役割と、プログラム言語としての役割があります。コマンドインタープリタとしてのシェルは、プロンプトを出して、ユーザの入力したコマンドラインを解釈して、プログラムを実行し、プログラムが終了したら再びプロンプトを出すということを司ります。 シェル以外の別のプログラムを起動するには、普通はシェルのプロンプトのもとでコマンドを入力して行います。
元来、シェルは sh という1種類しか存在しませんでした。sh は必要最小限の機能した持たなかったため、様々な亜種が作られることとなりました。シェルの種類によって機能が若干異なります。また。同じ機能でもシェルの種類によって文法が異なることがあります。
シェルの種類により、シェルスクリプトの文法も若干異なります。ログインシェルとして対話的に処理するには様々なシェルが使われていますが、色々なシェルの中で共通項的な位置にあり、どのUNIXシステムにも必ずあるシェルであるため、シェルスクリプトはBourneシェル用に書くのが普通になっています(プログラムとしての互換性を保つため)。
種類 | 説明 |
---|---|
sh | 様々な亜種が誕生したため、現在はそれらと区別するためにBourneシェル(略してBシェル)と呼ばれている。現在ではログインシェルとして使われることはほとんどないが、シェルスクリプトを書くためによく使われている。 |
bash | Bourne Again シェルは Bourneシェルの上位互換シェルである。Bourne シェルの構文を引き継ぎつつ、Bourneシェルにはない便利な機能を備えている。多くの Linux ディストリビューションで標準シェルとして採用されている。 |
csh | CシェルはC言語に似た構文を持つシェルである。Bourneシェルにはない便利な機能を備えている。Bourneシェルとは互換性がなく、同じ機能でもその構文が異なる。 |
ksh | KornシェルはBourneシェルの上位互換シェルであり、Kシェルとも呼ばれる。Bourneシェルの構文を引き継ぎつつ、Bourneシェルにはない便利な機能を備えている。 |
tcsh | TCシェルはCシェルの上位互換シェルである。 |
zsh | Zシェルはシェルの中でもとくに多機能なシェルである。Mac OS で標準シェルとして採用されている。 |
Bourneシェルがログインシェルであった場合、以下のファイルが存在すれば、その中に記述されたコマンドが実行されます。
通常 .profile ファイルには、端末の種類や環境を指定するコマンドが入っています。
Bourne Again シェルがログインシェルであった場合、以下のファイルが存在すれば、その中に記述されたコマンドが実行されます。
Bourne Again シェルがログインシェルでない場合、ユーザーのホームディレクトリの .bashrc が実行されます。
/etc/profile
/etc/profile とは、どのログインユーザでも共通の処理を記述したスクリプトシェルである。ログインシェルがshまたはbashの場合、ユーザがログインしたとき自動的に実行される。
~/.bash_profile
bashが対話型ログインシェルとして起動されると、/etc/profile ファイルからコマンドを読み込んで実行する。
次に、ログインユーザのホームディレクトリから次のファイルを上から順に検索して、最初に見つかったファイルからコマンドを読み込んで実行する。
これらのファイルが複数存在していても、最初に見つかったファイル以外はコマンドを読み込まない。たとえば、~/.bash_profile があれば ~/.bash_login は読み取られない。
var=value
bashで変数を設定するには、変数名に続けて等号と値を指定する。
$ EXAMPLE1=1
$ EXAMPLE2="foo"
配列の特定の要素に値を設定することができる。
var=`command`
変数にコマンドの実行結果を設定するには、実行するコマンドをバックスラッシュで囲む。
$ TODAY=`date`
$ echo "現在の時刻は $TODAY です。"
現在の時刻は Fri Aug 20 13:22:11 JST 2021 です。
local var=value
bashではローカル変数を使用できる。ローカル変数とは、変数を設定した関数内でのみ参照できる変数である。
bashでローカル変数を設定するには、localキーワードを指定して変数を設定する。
$ local EXAMPLE1=1
$ local EXAMPLE2="foo"
unset var
bashで変数を削除するには、unsetコマンドの引数に変数名を指定する。
$ unset EXAMPLE1
次の文字はシェルに対しては特別な意味を持ちます。
$ ; & ( ) | ^ < > 復帰改行 空白文字 タブ
これらの文字をメタキャラクタと呼びます。メタキャラクタのうち、次の文字はクォートしない(後述の説明を参照)限りワード(単語)の終わりを表します。
; & ( ) | ^ < > 復帰改行 空白文字 タブ
次の例は、word1;word2 という文字列を画面に出力するのではなく、word1 という文字列を画面に表示した後、word2 というコマンドを実行する、という意味でシェルは解釈します。
$ echo word1;word2
メタキャラクタの特別な意味を打ち消して、通常の文字として扱うには、次に示す3種類の方法があります。
メタキャラクタの特別な意味を打ち消して、文字自身を表すことをクォートと言います。シェルは、特定の文字をクォートして、それらが特別の意味を持たないようにすることがあります。
単一の文字をクォートするのに用いる \ は、コマンド実行前にワードから取り除かれます。\ と復帰改行との組み合せは、コマンドとパラメタの置換前にワードから取り除かれます。
一対の単一引用符(')で囲まれたすべての文字(ただし単一引用符は除く)は、シェルによってクォートされます。円記号は、一対の単一引用符で囲まれていれば特殊な意味を持ちません。 単一引用符は、一対の二重引用符で囲めばクォートされますが ( 例 "'" ) 、一対の単一引用符で囲んでもクォートされません。
一対の二重引用符 ("") の中では、パラメタとコマンドの置換が実施され、シェルは、その結果をクォートして、ブランクの解釈とファイル名の生成が行われないようにします。 $* が一組の二重引用符で囲まれている場合、定位置パラメタは置換され、クォートされ、クォートされた空白で分けられます ("$1 $2 ...") 。 しかし $@ が一組の二重引用符で囲まれている場合は、定位置パラメタは置換され、クォートされ、クォートされていない空白 ("$1" "$2" ... ) で分けられます。 \ は \、`、"、$ といった文字をクォートします。 \ と復帰改行との組み合せは、コマンドとパラメタの置換前にワードから取り除かれます。 バックスラッシュが \、`、"、$、および復帰改行以外の文字の前に付く場合は、バックスラッシュ自体がシェルによってクォートされます。
bashを対話的に実行しているとき、コマンドを読み取る用意ができたら、優先プロンプトPS1が表示される。コマンドを完了するために、さらに入力が必要な時は、2次プロンプトPS2が表示される。
PS1はプロンプトとして表示する文字列を設定する変数である。プロンプトの文字列には次の表に示す特殊文字を使うことができる。
特殊文字 | 説明 |
---|---|
\h | ホスト名 |
\u | 現在のユーザ名 |
$ PS1="\u@\h$ "
tsuka@examplehost$ PS1="$ "
$
alias
別名を全て表示します。
alias 別名=値
別名を設定します。
unalias 別名 ...
別名を削除します。
unalias -a
全ての別名を削除します。
case コマンドは、処理の流れ(フロー)を制御する構文です。変数の値によって、実行するアクションを変えることができます。
case 変数 in [ パターンのリスト ) コマンドリスト ;; ] ... esac
case コマンドは、変数 に一致する最初の パターンのリスト に対応した コマンドリスト を実行します。 パターンの形式は、ファイル名生成に使用される形式と同じです。 ただしスラッシュ、先行するドット、およびスラッシュ直後のドットは、明示的に一致しなくてもかまいません。
パターンのリストには、ひとつ以上の値を指定します。複数の値を列挙するには、パイプ記号(|)で区切ります。
変数の値がパターンのリストのいずれかに一致すると、対応するコマンドリストを実行します。コマンドリストには、0個以上のコマンドを指定します。複数のコマンドを列挙するには、セミコロン記号(;)または改行で区切ります。コマンドリストの終端は、;; で表します。
case "$0" in
-sh | -ksh | -jsh)
echo "hello"
;;
esac
case $? in
0)
echo "hello"
;;
1)
echo "world"
;;
esac
cd (change directory) とは、現在の作業ディレクトリを変更する組み込みコマンドである。
$ cd /home/tsuka
式を評価したうえでシェルのコマンドとして実行する。
eval [ argument ... ]
次のシェルスクリプトを実行すると $var=/tmp
がエラーとなり、変数tmp_dir
が設定されない。
#!/bin/sh
var=tmp_dir
$var=/tmp
echo $var
$ eval1
eval1: tmp_dir=/tmp: 見つかりません。
eval
を使うと、$var=/tmp
が tmp_dir=/tmp
と評価され、変数tmp_dir
が設定されるようになる。
#!/bin/sh
var=tmp_dir
eval $var=/tmp
echo $var
$ eval2
/tmp
exit はシェルを終了させるコマンドです。呼び出し元のシェルまたはシェルスクリプトを、数値で指定した終了ステータスで終了させます。
exit 1
数値を省略すると、最後に実行されたコマンドの終了ステータスがシェルの終了ステータスになります。
exit
これは、最後に実行したコマンドが返した10進数を指定したときと同じです。
exit $?
Bourne Againシェルで変数をエクスポートするには、シェル組み込みコマンドのexportを実行する。
export [[name[=word]] ...
変数に値を代入するのと、変数のエクスポートを同時に行うことができる。たとえば、
$ PATH=/usr/local/HULFT/bin:$PATH
$ export PATH
は、次のようにすることができる。
$ export PATH=/usr/local/HULFT/bin:$PATH
$n+1 ... から始まる一連の定位置パラメタを $1 ... に 再命名 (リネーム) します。nを省略すると、1 とみなされます。
shift [n]
$ cat example.sh
echo $1 $2 $3
shift 1
echo $1 $2
shift 1
echo $1
$ sh example.sh foo bar baz
foo bar baz
bar baz
baz
bash の until 文を使うと、終了条件を満たすまで特定の処理を繰り返すことができる。
until [ condition ]
do
# do something
done
until 文を用いて処理を繰り返す例を以下に示す。
$ more example.sh
#!/bin/bash
cnt=1
until [ $cnt -gt 3 ]
do
echo $cnt
let cnt++
done
$ bash example.sh
1
2
3
while コマンドは、処理の流れ(フロー)を制御する構文です。指定した条件を満たす間、特定のアクションを繰り返し実行させることができます。
while [ condition ]
do
# do something
done
while コマンドは、while コマンドリスト1 を繰り返し実行し、コマンドリスト1 中の最後のコマンドの終了ステータスが 0 の場合、do コマンドリスト2 を実行します。それ以外の場合、ループは終了しま す。 do コマンドリスト2 中のコマンドを実行しない場合、while コマンドは 0 の終了ステータスを返します。 ループ終了条件の判定を逆にするには、while の代わりに until を使用します。
while 文を用いて処理を繰り返す例を以下に示す。
$ more example.sh
#!/bin/bash
cnt=1
while [ $cnt -lt 4 ]
do
echo $cnt
let cnt++
done
$ bash example.sh
1
2
3
いくつかのコマンドをまとめて関数にすることができます。主にシェルスクリプト内で使用します。
関数名 () { コマンド ... }
関数を呼び出すときには、関数名を記述します。
関数名
関数を使用したシェルスクリプトの例を次に示します。
#!/bin/sh
func1()
{
echo 関数が呼ばれました。
}
func1
関数には引数を渡すこともできます。関数内で引数を参照するには、定位置パラメーター( $ + 数字 )を使用します。第1パラメーターが $1、第2パラメーターが $2 で参照できます。
#!/bin/sh
func2()
{
echo 関数が呼ばれました。引数は $1 と $2 と $3 です。
}
func2 para1 para2 para3
シェルのプログラミングはファイルからの入力で行います。コマンドラインからの入力と違い、いくつもの命令を一括して実行できるのが利点です。この、いくつものコマンドを手順に応じて編集したファイルをシェルスクリプトと言います。シェルは条件分岐や繰り返しといった制御命令を持っていますので、複雑な手順を持ったシェルスクリプトを作成することも可能です。
シェルスクリプトの文法は、コマンドラインからの入力のそれと基本的に同じです。大きな違いは、シェルスクリプトはまとめてテキストファイルとして記述し、実行することができるという点です。
カレンダーを表示するシェルスクリプトの例を次に示します。
echo "=== カレンダー =="
cal
echo "================="
シェルスクリプトを実行する方法は、次の2通りあります。
ファイル名を引数としてシェルを実行することで、シェルスクリプトを実行することができます。
% csh scriptfile
chmodコマンドでスクリプトファイルに実行権を与えることで、スクリプトファイルをコマンドラインから直接実行することができます。
$ chmod +x scriptfile
$ scriptfile
スクリプトファイルに実行権を与えてコマンドラインから直製実行した場合、スクリプトファイル内でシェルの種類を指定していなければ、Bourneシェルで実行されます。 シェルの種類を指定するには、スクリプトファイルの第1行目に #!
に続いて、使用するシェルを絶対パスによる表現で指定します。
コメント(注釈)をつけるには、シャープ記号を用います。シャープ記号から文末までの文字列はコメントと解釈され、実行には影響を及ぼしません。
echo "hello world" #コメント文
ピリオドに外部スクリプトファイルのパスを指定すると、そのスクリプトファイルを読み込んで実行する。
. path
シェルスクリプトを実行する際、引数を渡すことができます。
スクリプトファイルに実行権を与えた場合は、次のようになります。
n番目の引数の値は、$n で表されます。たとえば、1番目の引数の値は $1
で参照することができます。 $0
はシェル・スクリプトのファイル名を表します。
引数の個数は、$# で表されます。
$ cat showpara
echo $# $0 $1 $2
$ sh showpara p1 p2
2 showpara p1 p2
スクリプト内で実行するコマンドを表示するには、次に示す2つの方法がある。
set -x
と記述するシェルの引数に -x オプションを指定する例を次に示す。
$ cat script
echo current working directory
pwd
$ sh script
current working directory
/home/nakajima
$ sh -x script
+ echo current working directory
current working directory
+ pwd
/home/nakajima
スクリプト内に set -x
と記述する例を次に示す。
$ cat script
#!/bin/sh
set -x
echo current working directory
pwd
$ script
+ echo current working directory
current working directory
+ pwd
/home/nakajima
実行するコマンドとその引数を表示するのを止めるには、シェルスクリプトにset +x
と記述する。
シェルにはジョブの中断や再開、フォアグラウンド、バックグラウンドの切り替えなどのジョブ制御機能があります。
コマンドを実行中に ^Z (Ctrl + Z) を押すと、コマンドの実行を一時停止することができます。コマンドを一時停止すると、プロンプトが表示されて、他のコマンドを実行することができます。
一時停止したコマンドにはジョブ番号が付けられます。ジョブ番号を表示するには、jobs というシェル・コマンドを使用します。
一時停止したコマンドの実行を再開するには、プロンプトから fg というシェル・コマンドを実行します。
% cat
hello
hello
^Z
停止 (利用者要求による)
% cat hello
hello
% fg
cat
world
world
%
シェルの種類によってはファイル名の補完ができます。 コマンドラインからファイル名を入力する際、先頭の何文字かを入力してから何らかのキーを押すと、シェルが作業用ディレクトリからその文字列を含むファイル名を検索して、残りの文字を埋めます。 コマンドラインからの操作ではファイル名を入力する機会が多いので、ファイル名の補完機能があると便利です。
Bourneシェルにファイル名の補完機能はありません。
bash では Esc キーを 2 回押すと、ファイル名が補完されます。 例えば、作業用ディレクトリに mytext というファイルがある場合、vi my と入力して Esc キーを押すと、my という文字列が自動的に mytext というファイル名に補完されます。
もし、同一の名前をもつファイルがあったら、補完可能な部分まで表示されるので、残りはキーボードから入力します。
カンマ区切りの文字列をブレースで囲んだものは、個々に展開される。
$ echo {a,b,c}
a b c
$ echo mari{na,ri}
marina mariri
$ echo /{s,}bin
/sbin /bin
下記はcopy /home/marina/file /home/marina/file.bak
と展開される。
$ copy /home/marina/file{,.bak}
環境変数はシェル変数とほぼ同じです。シェル変数との違いは、起動したプロセス(子プロセス)に自動的に値がエクスポートされか否かです。 シェル変数はそのシェル固有の変数であり、シェルから起動したプロセスに変数は引き継がれません。 対して環境変数は、シェルから起動したプロセスに変数が引き継がれます。
Bourneシェルの場合、シェル変数をエクスポートすることで環境変数と扱います。
$ PATH=/bin:/usr/bin:/usr/sbin
$ export PATH
値の設定とエクスポートを同時に行うこともできる。
$ export PATH=/bin:/usr/bin:/usr/sbin
指定された 変数名 群に対し、後で実行されるコマンドの環境へ自動的にエクスポートされるようにマークを付けます。 引数を省略すると、現在のシェル実行中にエクスポートのマークが付けられた変数名を一覧表示します。 親シェルからエクスポートされた変数名は、現在のシェル実行中に再びエクスポートされた場合にだけ一覧表示されます。 関数名はエクスポートされません。
変数をエクスポートする例を次に示します。
$ var1=exported var2=notexported
$ export var1
$ echo $var1
exported
$ echo $var2
notexported
$ sh
$ echo $var1
exported
$ echo $var2
$
次に挙げる環境変数はシェルが使用するもので、意味は既に定義済みです。
変数名 | 意味 |
---|---|
HOME | cdコマンドのデフォルト引数。通常はホームディレクトリです。 |
PATH | コマンド用検索パス。 |
CDPATH | cd コマンドの検索パス |
このパラメタにメールファイルの名前がセットされていて、かつ MAILPATH パラメタが設定されていない場合、シェルは指定されたファイルにメールが到着するとユーザーに通知します。 | |
PS1 | 1 次プロンプト文字列。 |
PS2 | 2 次プロンプト文字列。 |
SHELL | シェルは、呼び出されると、このパラメタが示す名前が環境中に存在するかを確かめます。 |
LANG | 国際化情報を指定するのに用いる文字列。ユーザーはこの情報を利用して、さまざまな国の慣習に従って作業を進めることができます。 |
LC_ALL | 空文字列でない正当な値に設定されていれ ば、 LANG およびすべての LC_* 変数の値に代わって使用されます。 |
LC_COLLATE | 使用する文字照合順序を指定します。 |
LC_CTYPE | 文字分類、文字変換および複数バイト文字の幅を指定します。 |
LC_MESSAGES | 使用するメッセージデータベースの言語を指定します。 |
コマンドには標準的な入力デバイスが1つ、標準的な出力デバイスが2つ(正常時の出力とエラー時の出力)あります。これらをそれぞれ標準入力、標準出力、標準エラーと呼びます。通常、標準入力はキーボードに、標準出力と標準エラーはディスプレイに割り当てられています。
種別 | ファイル記述子 | デバイス |
---|---|---|
標準入力 | 0 | キーボード |
標準出力 | 1 | ディスプレイ |
標準エラー | 2 | ディスプレイ |
これらを通常のデバイスではなく、ファイル等に変更することをリダイレクトといいます。
指定したファイルを標準入力(ファイル記述子0)として使用します。
指定したファイルを標準出力(ファイル記述子1)として使用します。ファイルが存在しない場合は作成します。ファイルが存在していれば、ファイルの長さを 0 にします。
指定したファイルを標準出力として使用します。ファイルが存在する場合、(EOF までシークした後 ) そのファイルに出力を追加します。ファイルが存在しない場合は、ファイルを作成します。
指定したファイル記述子(0以上の整数)に対応するファイルを標準入力として使用します。
指定したファイル記述子に対応するファイルを標準出力として使用します。
標準入力をクローズします。
標準出力をクローズします。
上記のいずれかの前に数字が付く場合、その値が (デフォルトの 0 または 1 の代わりに) 該当ファイルに対応したファイル記述子となります。
command 2>&1
この例では、現在ファイル記述子 1 に関連しているファイルに、ファイル記述子 2 を関連付けます。
リダイレクションを指定する場合、記述する順序が重要になります。シェルは、リダイレクション記述を左から右へ評価します。
command 1>xxx 2>&1
上記の例では、まず xxx というファイルにファイル記述子 1 を関 連付けます。次に、ファイル記述子 1 に関連するファイル ( つま り xxx) に、ファイル記述子 2 を関連付けます。リダイレクションの向きが逆であれば、まずファイル記述子 2 を端末に関連付け (ファイルを記述子 1 が既に端末に関連付けられているとみなし) 、次にファイル記述子 1 をファイル xxx に関連付けます。