shell脚本中的安全rm -rf函数

Max*_*Max 7 regex bash sed

这个问题类似于在*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目录下挂载的文件系统上执行的).

注意事项:

  • 测试不是很好
  • 不打算用于可能包含'..'或'.'的路径.
  • 不应与用户提供的路径一起使用
  • 带有星号的rm -rf可能会失败,如果$ SOMEPATH中有太多文件或目录(因为命令行长度有限) - 这可以通过'for'循环或'find'命令修复

Spl*_*iFF 7

我发现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应该是一个非法的命令,因为充其量是执行无操作,更糟糕的是它可能导致意外的行为,但它就是它的本质.

  • 而不是`cd $SOMEPATH`,你应该写`cd "${SOMEPATH?}"`。`${varname?}` 符号确保如果变量未设置或为空(这样 `&& ...` 部分永远不会运行),则扩展失败并显示警告消息;双引号确保`$SOMEPATH` 中的特殊字符,例如空格,不会产生不良影响。 (3认同)

dhi*_*ill 5

set -u当使用未初始化的变量时,有一个bash 指令会导致退出。我在这里读到了它,并举rm -rf了一个例子。我想这就是你要找的。这是设置的手册


小智 2

我认为“rm”命令有一个参数以避免删除“/”。一探究竟。