这个问题类似于在*nix中清空目录最安全的方法是什么?
我正在编写bash脚本,它定义了几个路径常量,并将它们用于文件和目录操作(复制,重命名和删除).通常有必要做以下事情:
rm -rf "/${PATH1}"
rm -rf "${PATH2}/"*
Run Code Online (Sandbox Code Playgroud)
在开发这个脚本的过程中,我想保护自己免受类似PATH1和PATH2等名称的错误输入,并避免将它们扩展为空字符串,从而导致擦除整个磁盘.我决定创建特殊的包装器:
rmrf() {
if [[ $1 =~ "regex" ]]; then
echo "Ignoring possibly unsafe path ${1}"
exit 1
fi
shopt -s dotglob
rm -rf -- $1
shopt -u dotglob
}
Run Code Online (Sandbox Code Playgroud)
这将被称为:
rmrf "/${PATH1}"
rmrf "${PATH2}/"*
Run Code Online (Sandbox Code Playgroud)
正则表达式(或sed表达式)应该捕获像"*","/*","/**/","///*"等路径,但允许路径,如"dir","/ dir","/ dir1/dir2 /","/ dir1/dir2/*".另外我不知道如何在"/ dir with space/*"的情况下启用shell globbing.有任何想法吗?
编辑:这是我到目前为止提出的:
rmrf() {
local RES
local RMPATH="${1}"
SAFE=$(echo "${RMPATH}" | sed -r 's:^((\.?\*+/+)+.*|(/+\.?\*+)+.*|[\.\*/]+|.*/\.\*+)$::g')
if [ -z "${SAFE}" ]; then
echo "ERROR! Unsafe deletion of ${RMPATH}"
return 1
fi
shopt -s dotglob
if [ '*' == "${RMPATH: -1}" ]; then
echo rm -rf -- "${RMPATH/%\*/}"*
RES=$?
else
echo rm -rf -- "${RMPATH}"
RES=$?
fi
shopt -u dotglob
return $RES
}
Run Code Online (Sandbox Code Playgroud)
预期用途是(注意引号内的星号):
rmrf "${SOMEPATH}"
rmrf "${SOMEPATH}/*"
Run Code Online (Sandbox Code Playgroud)
其中$ SOMEPATH不是system或/ home目录(在我的例子中,所有这些操作都是在/ scratch目录下挂载的文件系统上执行的).
注意事项:
我发现bash中的rm存在很大危险,因为bash通常不会因错误而停止.这意味着:
cd $SOMEPATH
rm -rf *
Run Code Online (Sandbox Code Playgroud)
如果更改目录失败,则是非常危险的组合.更安全的方式是:
cd $SOMEPATH && rm -rf *
Run Code Online (Sandbox Code Playgroud)
这将确保rf不会运行,除非你真的在$ SOMEPATH.这并不能保护您免受糟糕的$ SOMEPATH的影响,但它可以与其他人提供的建议相结合,以帮助您使脚本更安全.
编辑:@placeybordeaux指出,如果$ SOMEPATH未定义或为空cd,则不将其视为错误并返回0.鉴于此答案应视为不安全,除非$ SOMEPATH首先被验证为现有且非空.我相信cd没有args应该是一个非法的命令,因为充其量是执行无操作,更糟糕的是它可能导致意外的行为,但它就是它的本质.