我希望 shell 能够警告我可能会犯的错误。
如何防止命令cmd2
在cmd1
.
例如:
$ tar tf file.tar
$ rm !$
这里,我只是忘记了我列出了文件而不是提取其内容。
我正在寻找一个通用的解决方案,它根据前一个命令的名称和返回值以及当前命令进行选择。
答案1
在 bash 中,您可以设置shopt -s histverify
哪一项将阻止历史记录被一步展开和执行。这里,第一次按 时,上面的内容$ rm !$
将扩展为,允许您在再次按执行之前进行检查或编辑。 更通用的解决方案将转向$ rm file.tar
EnterEnter
“做我的意思”领土,需要一个程序来事后猜测你的意图。
答案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
尽管在您的特定情况下,第二个命令仍然会运行,因为它没有错误,即使它没有执行您想要的操作。