コマンドが成功した場合にのみ出力を抑制するにはどうすればよいですか?

コマンドが成功した場合にのみ出力を抑制するにはどうすればよいですか?

通常、成功したヘルパーコマンドの出力を抑制してスクリプト出力を簡素化したいと思います。

ただし-q、時々失敗した場合、それを使用すると出力が非表示になり、エラーを理解できません。また、これらのコマンドは出力をstderr

コマンド出力を抑制する方法はありますか?成功する限り

たとえば(これに限定されない)、次のようになります。

mycommand | fingerscrossed

すべてが順調に進むと、fingerscrossed出力をキャプチャして破棄します。それ以外の場合は、標準またはエラー出力(何でも)に反映されます。

答え1

moreutils'chronicコマンドは次のことを行います。

chronic mycommand

出力は失敗しない限り飲み込まれmycommand、失敗すると出力が表示されます。

答え2

私はこの簡単な答えを見つけました。これは別の質問です:

output=`mycommand 2>&1` || echo $output

奇跡的に動作します!

答え3

### do this bit once at the top of your script
divert=
exec 3<>"${divert:=$(mktmp)}" 4<>/dev/null
rm -- "$divert"; unset divert
### then do this bit as often as needed
command >&3 2>&3
cat <&3 >&"$(((RTN=$?)?2:4))"

これはトリックを行う必要があります。各出力をバッファリングします。command削除された一時ファイルに保存し、/dev/null戻り状態がゼロでないかどうかに応じて出力をstderrにサイフォンします。一時ファイルは早期に削除されるため、現在のシェルとサブプロセスのファイル記述子を除くすべてのプロセスで読み取ることはできません。/proc/$pid/fd適切な権限がある場合はスヌーピングはありません)、完了後のクリーンアップは必要ありません。

Linuxシステムにはより便利なソリューションがあるかもしれません。

divert(){
    "$@" >&3 2>&3 ||
    eval "cat <&3
          return $?"
}   3<<"" 3<>/dev/fd/3

...ほとんどのシェルでは、次のように呼び出すことを除いて、他のシェルと非常によく似ていますdivert some simple-command with args"$@"しかし、for dash、またはここでドキュメントを実行するためにパイプを使用する他のシェルの高出力コマンドに注意してくださいyash。そのシェルでは、パイプバッファがいっぱいになる可能性があると思います。(Linuxのデフォルト値は約128kbです.)デッドロックです。しかし、これはksh、、、、mkshまたはBourneシェルのbash問題にならないでくださいzsh。すべて上記で明示的に行ったのと基本的に同じですexec

答え4

自分だけの慢性疾患を作る

my_chronic() {
  tmp=$(mktemp) || return # this will be the temp file w/ the output
  "$@"  > "$tmp" 2>&1 # this should run the command, respecting all arguments
  ret=$?
  [ "$ret" -eq 0 ] || cat "$tmp"  # if $? (the return of the last run command) is not zero, cat the temp file
  rm -f "$tmp"
  return "$ret" # return the exit status of the command
}

関連情報