防止一个命令在另一个命令之后执行

防止一个命令在另一个命令之后执行

我希望 shell 能够警告我可能会犯的错误。

如何防止命令cmd2cmd1.

例如:

$ tar tf file.tar
$ rm !$

这里,我只是忘记了我列出了文件而不是提取其内容。

我正在寻找一个通用的解决方案,它根据前一个命令的名称和返回值以及当前命令进行选择。

答案1

在 bash 中,您可以设置shopt -s histverify哪一项将阻止历史记录被一步展开和执行。这里,第一次按 时,上面的内容$ 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 函数仍然可以在那里工作,因此您不必将所有内容都塞到单行、单个变量中。

$ # 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),因为它预先运行。结合这两种方法时要小心,因为输出/操作将加倍:

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

要使陷阱中断命令,您必须启用extdebug( shopt -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

在 shell 初始化脚本中(假设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

尽管在您的特定情况下,第二个命令仍然会运行,因为它没有错误,即使它没有执行您想要的操作。

相关内容