あるコマンドが別のコマンドの後に実行されないようにする

あるコマンドが別のコマンドの後に実行されないようにする

私は私が犯すことができる間違いについてシェルが私に警告したいと思います。

NETcmd2でコマンドが実行されないようにする方法cmd1

たとえば、

$ tar tf file.tar
$ rm !$

ここでは、コンテンツを抽出するのではなく、ファイルを一覧表示したことを忘れていました。

私は現在のコマンドだけでなく、以前のコマンドの名前と戻り値に基づいて選択する一般的な解決策を探しています。

答え1

shopt -s histverifyBashでは、履歴が1段階に拡張され実行されるのを防ぐための項目を設定できます。ここで最初に押すと上記の内容が展開$ rm !$され、[再実行]をクリックする前に確認または編集できます。より一般的な解決策は次のとおりです。$ rm file.tarEnterEnter
「私が望むようにしてください」領土、あなたの意図を推測するプログラムが必要です。

答え2

あなたは多くの一般的な答えを求めていますが、ある程度は比較的簡単です。

ただし、bashこの問題を解決するのに役立つ一般的なメカニズムが複数あります。プロンプトで何かを実行した後に実行する変数PROMPT_COMMANDを設定できます。

$ PROMPT_COMMAND='echo BOFH says hi!'
BOFH says hi!
$ man man
BOFH says hi!
$

これを使用して、最後に入力したコマンドを保存してから再読み込みして、後で使用するためにメモリに保存できます(この場合、履歴拡張は機能しません)。

$ PROMPT_COMMAND='history -a; tail -n1 ~/.bash_history'
PROMPT_COMMAND='history -a; tail -n1 ~/.bash_history'
$ wc < test.sh | grep .
 5 11 63
wc < test.sh | grep .

これで論理部分が出ます。これは完全にあなた次第です。質問の例をブロックするために、非常に単純なロジックを試してみましょう。覚えておくべきことは、bash機能がまだ機能しているので、すべてを1行、単一の変数に入れる必要がないことです。

$ # define the logic check
$ checkSanity() { grep -q "tar  *[tf][[:alpha:]]*[tf] " <<< "$@" && echo "be careful, don't delete this"; }
checkSanity() { grep -q "tar  *[tf][[:alpha:]]*[tf] " <<< "$@" && echo "be careful, don't delete this"; }
$ # feed it the last command
$ PROMPT_COMMAND='history -a; last=$(tail -n1 ~/.bash_history); checkSanity "$last"'
$ # simple test
$ tar tf test.sh 2>/dev/null 
be careful, don't delete this
$ tar xf test.sh 2>/dev/null 
$

もちろん、このアプローチはPEBKACを防ぐのに役立ちますが(特にsleep 3最後に追加する場合)、次のコマンド自体は中断されません。

もしそうなら本物必要なものは、事前に実行されるDEBUG信号(たとえば)をキャプチャします。trap 'echo "I am not deterministic, haha"' DEBUG出力/操作が倍増するため、これら2つの方法を組み合わせるときは注意してください。

$ df
/.../
$ trap 'tail -n1 ~/.bash_history' DEBUG
df
df
trap 'tail -n1 ~/.bash_history' DEBUG
trap 'tail -n1 ~/.bash_history' DEBUG

トラップこのコマンドを中断するには、そのトラップを有効にする必要がありますextdebugshopt -s extdebug)。また、履歴を保存し続ける必要はありませんが、$BASH_COMMAND今後のコマンドを確認することもできます。その後、ロジックチェッカーが誤った場合を検出した場合は1を返し、そうでない場合は0を返すことを確認します。

          extdebug
                  If set, behavior intended for use by debuggers is enabled:
    /.../
                  2.     If  the command run by the DEBUG trap returns a non-zero value, the next
                         command is skipped and not executed.


$ checkSanity() { if grep -q "tar  *[tf][[:alpha:]]*[tf] " <<< "$1"; then  echo "be careful, don't delete this"; return 1; fi; }
$ trap 'checkSanity "$BASH_COMMAND"' DEBUG
$ # simple test
$ tar tf test.sh 2>/dev/null 
be careful, don't delete this
$ tar xf test.sh 2>/dev/null 
$

答え3

この場合、コマンドのエラー警告によって利点が得られますrm

シェル初期化スクリプト(bash、so仮定)またはエイリアスを使用~/.bashrcできます。rm-i-I

alias rm="rm -i"

~からman 1 rm

   -i     prompt before every removal

   -I     prompt once before removing more than three files, or when
          removing recursively.  Less intrusive than -i, while still
          giving protection against most mistakes

より一般的な質問は「自分自身からシステムをどのように保護しますか?」です。前に議論した。要するに、やっていることに注意を払う、必要な場合にのみrootコマンドを実行します。

答え4

あなたの特定の状況に応じて、次のようにします。

tar tf file.tar
if [ -f file ]; then   # Assuming you meant to extract a file
  rm -f file.tar
else
  echo "file is missing. Command failed."
fi

エラーを確認し、最初のコマンドが成功した場合にのみ、次のコマンドを実行したい場合

some_command && another_command

ただし、特定の場合には、目的の操作を実行しなくてもエラーが発生しないため、2番目のコマンドは引き続き実行されます。

関連情報