for ループで開始されたプロセスを `wait` しますが、それ以前に開始された他のプロセスは待機しません。

for ループで開始されたプロセスを `wait` しますが、それ以前に開始された他のプロセスは待機しません。

実行中のバックグラウンド タスクがいくつかあるとします。ここで、さらに 2 つのバックグラウンド タスクを実行し、最後の 2 つのタスクだけを待機するとします。例:

# long running commands
sleep 60 &
sleep 60 &

# now wait only for these two:
sleep 5 & sleep 5 & wait; echo waited only for the 5s sleeps.

上記のコマンドの結果、echo コマンドは 60 秒間待機します。

自分ができるということがわかっている待機するにはpidまたはjobidを渡しますしかし、プロセスをforループで開始しているため、PID を簡単に取得することはできません。

これを試してみましたが、うまくいきませんでした:

{ sleep 3 & sleep 5 & } wait; echo did not wait :

sleep 10 & { sleep 3 ; sleep 3 ; }& wait %2; echo only wait 3s

追記:この質問はこのより単純な質問

答え1

サブシェルを開始できます:

{ sleep 20 && echo second output ; }
( sleep 2 & wait && echo first output ) 

waitサブシェル内のコマンドはそこでのみ有効になります。

答え2

より簡単な質問に対する @Kusalananda のガイダンスに基づいて、この例を思いつきました。最も簡単な例ではないかもしれませんが...

以下のコードはすべて対話型シェル内にあります。読みにくいので、回答のためにコードをいくつかの部分に分割しました。

bashバージョン 4.1 およびそれ以前のバージョンでは、!内の は""対話型シェルで履歴置換をトリガーすることに注意してください (これはリリース 4.2 で修正されました)。それが私が騙されていたことです。本当に引用符で囲みたい場合は、 を$!使用できます"$! "。末尾のスペースにより、履歴置換が開始されなくなります。

unset to_wait; 

date; 
sleep 3 & 

for i in 1 2 3; do 
    sleep 1 &
    # Don't put the ! in "" or you'll get an `event`. 
    to_wait+=( $! ); 
done; 
wait "${to_wait[@]}"; 

date; 
echo waited 1s for inner processes; 

# wait for the rest of the processes (just for illustration)
wait; 

date; 
echo waited 3s for outer process;

関連情報