web-dev-qa-db-ja.com

シェルスクリプトの特定のエラーを無視する

多くのエラーをスローする可能性のあるシェルスクリプトの小さな断片があります。現在、すべてのエラーでグローバルに停止するようにスクリプトを設定しています。ただし、この小さなサブセクションは少し異なります。

以下がスニペットです。

recover database using backup controlfile until cancel || true; 
auto

私はこれが最終的に「ファイルが見つかりません」エラーをスローすることを期待しています。しかし、私はこのエラーで実行を継続したいと思います。その他のエラーについては、スクリプトを停止したいと思います。

これを達成する最良の方法は何でしょうか?

Bashバージョン3.00.16

46
Stunt

特定のコマンドのエラーをbashが無視しないようにするには、次のように言います。

_some-arbitrary-command || true
_

これにより、スクリプトが続行されます。たとえば、次のスクリプトがある場合:

_$ cat foo
set -e
echo 1
some-arbitrary-command || true
echo 2
_

実行すると戻ります:

_$ bash foo
1
z: line 3: some-arbitrary-command: command not found
2
_

コマンドラインに_|| true_がない場合、次のようになります:

_$ bash foo
1
z: line 3: some-arbitrary-command: command not found
_

手動 からの引用:

失敗したコマンドがwhileまたはuntilキーワードの直後のコマンドリストの一部である場合、ifステートメントのテストの一部である場合、シェルは終了しません。 _&&_または_||_リストで実行されるコマンド、最後の_&&_または_||_に続くコマンド、パイプライン内の最後のコマンド、またはコマンドの戻りステータスの場合を除く_!_で反転されています。 ERRのトラップは、設定されている場合、シェルが終了する前に実行されます。

編集:実行を継続するように動作を変更するためにifのみ実行_some-arbitrary-command_は_file not found_を一部として返しましたエラー、あなたは言うことができます:

_[[ $(some-arbitrary-command 2>&1) =~ "file not found" ]]
_

例として、次を実行します(_MissingFile.txt_という名前のファイルは存在しません):

_$ cat foo 
#!/bin/bash
set -u
set -e
foo() {
  rm MissingFile.txt
}
echo 1
[[ $(foo 2>&1) =~ "No such file" ]]
echo 2
$(foo)
echo 3
_

これにより、次の出力が生成されます。

_$ bash foo 
1
2
rm: cannot remove `MissingFile.txt': No such file or directory
_

_echo 2_は実行されましたが、_echo 3_は実行されなかったことに注意してください。

98
devnull

つかいます:

command || :

:は、常に成功を返すbashビルトインです。そして、上で議論したように、||短絡して、RHSが失敗した(ゼロ以外の値を返す)場合にのみRHSが実行されます。

「true」を使用する上記の提案も機能しますが、「true」は外部プログラムであるため非効率的です。

21
Chris Cogdon