注意:如果你在谷歌上搜索这个问题的标题,除非你知道它应该做什么,否则不要使用这个脚本。
这是bash 3+中的一个脚本,用于防止rm *和rm -rf *意外调用和错误删除重要文件。我把它放在我的~/.bash_aliases里。
alias rm='set -f;rm'
rm(){
if [[ "$-" == *i* ]]
then
if [ "$1" = "*" ] || [ "$2" = "*" ] || [ "$1" = "./*" ] || [ "$2" = "./*" ]
then
echo "Abort: refusing to remove *, please go to the parent folder and do rm /*" 1>&2
set +f
return 1
fi
fi
set +f
/bin/rm -i $@
}
set +f我想知道是否有任何漏洞,是否可以改进。
发布于 2019-03-09 03:18:06
我看到的漏洞是,只检查前两个参数。你可以检查所有这些:
rm() {
[[ $- == *i* ]] && for arg
do
if [[ $arg = "*" || $arg = "./*" ]]
then
# abort
fi
done
# do the rm这种检查将错过其他危险的通配符,如**或?*。您可以通过自己展开*来获得更安全的检查,然后查看展开的参数是否包含相同的文件列表:
# alias not needed here; we want globs to be expanded
rm() {
declare -a star=(*)
declare -a dotslashstar=(./*)
if [[ "$@" == *"${star[@]}"* || "$@" == *"${dotslashstar[@]}"* ]]
then
# abort..。但是,如果rm *.tmp和*匹配,那么就不能(例如)用*.tmp来清空满是临时文件的目录。
发布于 2019-03-09 12:37:20
这是一个bug:
/bin/rm -i $@
如果您尝试删除文件a b (名称中有空格),会发生什么情况?最有可能的是:
rm: a:没有这样的文件或目录,rm: b:没有这样的文件或目录。
始终编写"$@"而不是未引用的$@。
不幸的是,正如您在评论中指出的那样,这将导致另一个问题:包含全局的参数将被视为字面意思。总之,吃蛋糕也很难。
您可以通过遍历参数来缓解这个问题,如果您检测到一个glob,那么自己展开它:
for arg; do
if [[ $arg == *[*?]* ]]; then
expanded=($arg)
echo rm -i "${expanded[@]}"
else
echo rm -i "$arg"
fi
done这仍然不是完美的,因为当参数同时包含空格和全局时,它不会处理这种情况。一个健壮的解决方案将需要更多的努力,而不值得在Bash中进行。(请参见将艰苦工作委托给Python的这个例子。)
command绕过别名不要担心命令的绝对路径。使用command绕过别名:
command rm -i "$@"在echo "Abort: ..." 1>&2中,文件描述符1是多余的,您可以安全地省略它。
这是个小小的挑剔。当别名被执行时,它将执行set +f,而不管shell中的原始设置是什么,这可能是不一样的。这真的只是一个小小的挑剔,作为记录。我也不会在乎这些不切实际的细节。
发布于 2019-03-11 10:17:29
rm如果您开始依赖于这个安全网,那么您最终将在一个具有标准rm的系统上发生事故(例如,当您成为root用户并发现自己在管理任务中使用dash时)。
我建议
weijun_rm() {
# your safer implementation
}
rm() {
echo "Disabled - please use weijun_rm instead" >&2
return 1
}这将训练您不要使用rm来删除文件。当您的函数不可用并且必须使用真正的rm时,您将保持警惕,并格外小心地检查参数。
https://codereview.stackexchange.com/questions/215069
复制相似问题