for ループの開始後の進捗状況を表示します。

for ループの開始後の進捗状況を表示します。

for対話型セッションでループを開始しますbash。この問題では、ループが次のようになると想定できます。

for i in dir/*; do
    program "$i"
done > log

コマンドは予想よりはるかに長くかかりましたが、まだ実行されました。for現在実行中のループの進行状況を表示する方法。

非ソリューション:

  • よりlog
    次の理由で機能しません。 program静かに走ると予想されます。program検証人だと思えばいいです。出力なしでループが完了したら幸いです。
  • サイクルを停止します。一種の進行状況インジケータを追加します(例echo "$i":)。サイクルを再開してください。
    次の理由で機能しません。ループは数時間実行された。私は現在それに投資しているすべての時間とエネルギーを無駄にしたくありません。私はすべてが大丈夫だと思います。ただ気になって、今まで何が起こっているのか知りたいです。
  • Ctrl+Zそれからset -x; fg
    次の理由で機能しません。 bash使用中はサイクルは継続されませんfg。ループ内の現在/次のコマンドが実行されるまで、ループは終了しませんfg。自分で試してみてくださいfor i in {1..200}; do printf '%s ' $i; /usr/bin/sleep 0.5; done

ベストアンサー1

ワイルドカード文字はdir/*常に同じ順序で展開されます。この機能は現在の値と一緒に使用して$i進捗情報を表示できます。

$i現在の値は、システムで実行されているプロセスを確認することによって取得できます。これ次のコマンド現在実行中のインスタンスprogramとそのパラメータを印刷します。
複数のプロセスがある場合は、確認したいループを実行しているシェルで開始されたプロセスのみを一致させるオプションをprogram使用できます。--parent ...pgrepfor

ps -o args= -fp $(pgrep program)

手動で値を抽出し、$i次を使用して進行状況を確認します。

a=(dir/*)
n=$(printf %s\\0 "${a[@]}" | grep -zFxnm1 'the exact value of $i' | cut -f1 -d:) 
echo "Progress: $n / ${#a[@]}"

これは2つの仮定の下で機能します。

  1. dir/ループの実行中は内容は変更されません。programファイルが作成された場合、名前が変更または削除された場合は、番号が間違っている可能性があります。

  2. program新しいプロセスを開始するために呼び出されます。関数programの場合、bash子プロセスはありませんprogram。関数function自体が新しいプロセスを開始する別のプログラムを呼び出す場合は、そのサブルーチンを見つけることができます。しかし、programbash 組み込み(ネストされたコマンドを使用help)または純粋な bash 関数(組み込みbash機能を使用)の場合、幸運ではありません。

問題2があるfor場合、またはループの構造が質問と異なる場合(たとえば、さまざまなプログラムを含む非常に長いループ本文)、プロセスを調べることで問題を解決program < "$1"できます。lsof

おすすめ記事