私が正しい場合、コマンド置換、プロセス置換、パイプ、およびバックグラウンドタスクは、元のシェルではなくサブシェルで独自に指定されたコマンドを実行します。
ただし、コマンドがまたはjobs
の場合、dirs
その出力は元のシェルで直接実行されたときとまったく同じです。
echo $( jobs )
cat <(jobs)
jobs | less
echo $( dirs )
cat <(dirs)
dirs | less
dirs &
なぜそんなことですか?サブシェルがソースシェルからジョブスタックとディレクトリスタックを継承するのですか、それともこのサブシェルではなくソースjobs
シェルdirs
で実行されているのですか?
しかし、
jobs &
何も出力しません。なぜ他のコマンドと違うのですか?ありがとうございます。
答え1
この答えの最初の部分はと組み込まれているので、通常bashはサブシェルを呼び出す代わりに直接実行しますjobs
。dirs
$(jobs)
パイプや命令置換()やプロセス置換()がある場合も同様である<(jobs)
。
jobs &
バックグラウンドでコマンドを実行したり()明示的にサブシェルを要求した場合(.を使用)、そうでは( jobs )
ありません。
これは質問の最後の部分を説明します。サブシェルで実行すると、jobs
サブシェル自体のアクションが表示されます。
以下は、この概念をよく示す例です。
$ sleep 1001 &
[1] 15927
$ sleep 1002 &
[2] 15940
$ jobs
[1]- Running sleep 1001 &
[2]+ Running sleep 1002 &
$ ( sleep 1003 & jobs )
[1]+ Running sleep 1003 &
$ jobs
[1]- Running sleep 1001 &
[2]+ Running sleep 1002 &
jobs
サブシェルで実行すると、そのサブシェルに対するアクションのみが表示されることがわかります(この場合).sleep 1003
ここで要約すると、問題の中間部分を解決する必要があります。これがdirs &
(サブシェルで実行されているかのように( dirs )
)Pushdスタックに保存されているディレクトリがまだ表示される理由です。
DIRSTACK
これは、シェルがディレクトリリストを特殊な配列変数としてエクスポートし、この変数がサブシェルから継承されるためであることがわかりました。 (詳細はDIRSTACK
ここ.)
これがどのように機能するかを示す1つの方法は、サブシェルpushd
で使用し、元のシェルのディレクトリスタックにどのように影響しないかを確認することです。
$ dirs
~
$ pushd ~/tmp
~/tmp ~
$ ( dirs; pushd / >/dev/null; dirs )
~/tmp ~
/ ~/tmp ~
$ dirs
~/tmp ~
私はこれがあなたが要求したすべての問題を解決しなければならないと思います。
修正するjobs | less
:bashには、現在シェルでコマンドを実行できる特別な規定がありますjobs
(他の組み込みコマンドはそうではありません)。
コードには、サブシェルを生成せずに実行し、出力を別のコマンドにパイプできるjobs_hack
ように、後でチェックされる変数にチェックが格納されています。jobs
バラよりこここの機能を実装するソースコードの関連部分を理解してください。 (バッシュ4.4から)