サブシェル 別のシェルとして実行する
この ( ) のサブシェルを使うと、サブシェル内の内容がサブシェル上で(別の子プロセスとして)実行されます。文法的にはサブシェルの( )全体が1つの複合コマンドとなります。
カレントディレクトリの一時変更やシェル変数の局所的な仕様など、元のシェルの状態には影響を及ぼさずに一定の処理を行いたい場合、その部分のリストを( )で囲んで、サブシェルで実行させるようにします。
サブシェルは、元のシェルとは別の子プロセスになる為、子プロセス上のカレントディレクトリやシェル変数などが変化しても、実行元のシェルには影響しません。
サブシェル内ではシェル変数の代入のほか、シェル変数やその他のパラメータの操作に関する
・export
・read
・readonly
・set
・shift
・unset
などのコマンドの効果がサブシェル内のみになります。
ちょっとコメントがうざいかもしれませんが、サブシェルがどのような動きをするのか確認する為のシェルが以下です。
#!/bin/bash
pwd
(
# サブシェル内でカレントディレクトリ移動
cd /tmp
pwd
# サブシェル内で変数「TEST」を定義
TEST=test
# サブシェル内で変数「TEST」の確認
echo '$TEST(sub) = '$TEST
(
# サブシェル内でさらにサブシェルを作った時の変数「TEST」の確認
echo '$TEST(sub2) = '$TEST
)
# サブシェル内に戻ったので改めて変数「TEST」の確認
echo '$TEST(sub_again) = '$TEST
)
# サブシェルを全て抜けメインのシェルでのカレントディレクトリの確認
pwd
# サブシェルを全て抜けメインのシェルでの変数「TEST」の確認
echo '$TEST(shell) = '$TEST
そしてそのシェル(sub.sh)を実行した時の結果です。分かりやすくサブシェル内はインデントをかけて表示させています。
./sub.sh
/home/fedora
/tmp
$TEST(sub) = test
$TEST(sub2) = test
$TEST(sub_again) = test
/home/fedora
$TEST(shell) =
exit は通常とは違う動作をします
また、exitコマンドは、「.」コマンドで別のシェルを実行した先でexitした場合は、その段階で全てのシェルを終了させてしまいますが、
サブシェルの( ) 内でexitした場合はサブシェルだけが終了し、メインシェルに戻ることができます。
終了ステータス
( )内の最後に実行したコマンドの戻り値が終了ステータスになります。
サブシェルの標準出力をリダイレクト
( )で囲まれた全体がの1つの複合コマンドとして認識されるため、サブシェル全体の標準出力をログファイルにリダイレクト。という事もできます。
(
date
pwd
) > logfile.log
logfile.logは以下になります。
2100年 01月 01日 金曜日 00:00:00 JST
/root
一見似ているグループコマンド { } とは文法が異なる
1行で記載する場合、グループコマンドではスペースや;が必要になります。が、サブシェルではスペースも;もいりません。
サブシェルの場合
○(echo HelloWorld)
グループコマンドの場合
×{echo HelloWorld}
○{ echo HelloWorld;}