web-dev-qa-db-ja.com

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

通常は成功する二次コマンドの出力を抑制して、スクリプトの出力を簡略化したいと思います。

ただし、-qオンにすると、時々失敗するときに出力が非表示になるため、エラーを理解する方法がありません。さらに、これらのコマンドは出力をstderrに記録します。

コマンドの出力を抑制する方法はありますか成功した場合のみ

たとえば(これに限定されませんが)次のようなもの:

mycommand | fingerscrossed

すべてがうまくいけば、fingerscrossedは出力をキャッチして破棄します。それ以外の場合は、標準出力またはエラー出力(何でも)にエコーします。

22
Matthieu Napoli

この他の質問

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

魅力的な作品!

4
Matthieu Napoli

moreutils 'chronicコマンドはそれを行います:

chronic mycommand

失敗した場合を除き、mycommandの出力を飲み込みます。失敗した場合、出力が表示されます。

37
Stephen Kitt
### 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に吸い上げます。ゼロ。一時ファイルは事前に削除されるため、ファイル記述子の現在のシェルとその子以外のどのプロセスでも読み取ることができません(sneaky /proc/$pid/fd snoops with適切な権限)、そしてそれ終了時にクリーンアップする必要はありません。

おそらくLinuxシステムではより便利なソリューションです。

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

...ほとんどのシェルでは、divert some simple-command with argsのように呼び出すことができることを除いて、他のシェルとほとんど同じように機能します。 "$@"の高出力コマンドに注意してください。ただし、dashyash、またはパイプを使用してここのドキュメントを実行するその他のシェルの場合-これらのシェルでは、パイプバッファを埋める(linuxesではデフォルトで約128kb)なので、デッドロック。 kshmkshbashzsh、またはBourne Shellの場合は心配する必要はありません。これらはすべて基本的に同じです上記でexecを明示的に指定したもの。

11
mikeserv

通常、エラーが発生した場合、コマンドはstderrにメッセージを出力するため、タスクの場合はstdoutを抑制できます。

mycommand > /dev/null
9
Costas

自分を慢性的にする

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
}
4
Jacob Minshall

私は私のメイクファイルで次のようなことをしています:

if (mycommand) &> mycommand.log; then 
  echo success 
else 
  c=$?; 
  echo;echo -e "Bad result from previous command, see mycommand.log for more details";echo;
  command_to_run_on_fail
  (exit $c)
fi

それを自分の状況に適応させると、次のようなことができます。

if ! (mycommand) &> mycommand.log; then 
  c=$?; 
  cat mycommand.log
  rm mycommand.log
  (exit $c)
fi

したがって、「if」はコマンドを実行し、出力をmycommand.logにパイプします。 stdoutとstdoutを比較する必要がある場合は、パイプコマンド '&>'を '>'に変更する必要がある場合があります。コマンドが失敗した場合は、エラーコードをキャプチャし、mycommand.logの内容を出力して、mycommand.logを削除し、最後に元のエラーコードで戻ります。

(exit $ c)がないと、「rm」コマンドが返したものと一致する終了コードで戻ります。

最後に、1つのライナーが必要な場合は、このようなものが機能します。

mycommand &> mycommand.log || cat mycommand.log; rm mycommand.log
3
Jordan