设置“noclobber”有什么缺点吗?

设置“noclobber”有什么缺点吗?

鉴于zsh可以破坏给定命令的所有文件:

>*

我认为设置该选项noclobber是个好主意。

>| file如果我想在 bash 和 zsh 中使用默认的破坏行为,我总是可以使用。 (zsh 还允许替代语法>!file)。

我猜测noclobber由于 POSIX 兼容性,默认情况下未设置,但只是为了确定:

设置有什么缺点吗noclobber

noclobber有没有办法只为交互式 shell设置?

答案1

noclobber没有设置默认的原因是传统。作为用户界面设计的问题,最好让“创建这个新文件”成为简单的操作,并为更危险的操作“创建新文件或覆盖现有文件”设置额外的障碍。因此,这noclobber是一个好主意(>创建一个新文件,>|可能会覆盖现有文件),并且如果 shell 是在几十年后设计的,那么它很可能是默认值。

我强烈建议在交互式 shell 启动文件中使用以下内容(.bashrc.zshrc):

set -o noclobber
alias cp='cp -i'
alias mv='mv -i'

在每种情况下(重定向、复制、移动),目标都是在操作可能产生擦除某些现有数据的副作用时添加额外的障碍,即使擦除现有数据不是操作的主要目标。我没有列入rm -i此列表,因为擦除数据是rm.

请注意,noclobber并且-i安全网。如果它们触发,你做错了什么。所以不要用它们作为不检查你正在覆盖的内容的借口!关键是您应该检查输出文件不存在。如果你被告知file exists: foooverwrite 'foo'?,则意味着你犯了一个错误,你应该感到难过并更加小心。特别是,不要养成说yif 提示覆盖的习惯(可以说,别名应该是alias cp='yes n | cp -i' mv='yes n | mv -i',但按Ctrl+C会使输出看起来更好):如果您确实打算覆盖,请取消命令,移动或删除输出文件,然后再次运行该命令。

同样重要的是,不要养成触发这些安全措施的习惯,因为如果这样做,有一天您将使用一台没有您的配置的计算机,并且您将丢失数据,因为您所依赖的保护措施已失效。在那里。

noclobber只会为交互式 shell 设置,因为.bashrcor.zshrc只能由交互式 shell 读取。当然,您不应该以影响脚本的方式更改 shell 选项,因为它可能会破坏这些脚本。

答案2

缺点是,如果你习惯了noclobber活跃,有一天你会使用一个它不适合的系统。不是活跃起来,你会愉快地执行一个有潜在危险的命令,期望它能noclobber拯救你……但它不会。然后,您必须希望有一个足够新的备份来恢复您损坏的数据,因为您认为系统会首先要求您进行确认。

答案3

noclobber~/.bashrc(for bash) 或~/.zshrc(或更准确地说$ZDOTDIR/.zshrc, for )中设置shell 选项zsh将使其在交互式 shell 会话中处于活动状态。

非交互式 shell(脚本)不会读取这些文件。

Shell 选项通常不会从父 shell 继承。

这意味着您应该能够在这些文件中设置选项,而无需修改现有脚本中的行为,除非脚本显式来源这些文件。

我认为这样做的唯一缺点是您会反复忘记您已经设置了该选项,至少在开始时是这样。后来,与所有这些类型的事情一样,您将开始习惯性地使用>|,即使您实际上可能不想破坏文件(就像别名为 的人一样rmcp并且设置了始终mv选项-i,最终开始总是使用-f在命令行上)。

答案4

我建议还为命令添加别名rm
我将接受的答案和我的建议结合起来,以使其变得简单。

# safe overwrite
set -o noclobber
alias cp='cp -i'
alias mv='mv -i'
alias really-rm="/bin/rm"
# safe remove
move_to_trash() { 
    local trash_dir
    trash_dir="${HOME}/.trash"
    
    if [ ! -d "${trash_dir}" ]; then
        echo "Trash directory doesn't exist. Creating..."
        mkdir "${trash_dir}"
        echo "Created!"
    fi
    
    local new_dir_name
    new_dir_name="${trash_dir}/$(date +%Y-%m-%d_%H-%M-%S)/"
    mkdir "${new_dir_name}"
    
    echo "Moving to: ${new_dir_name}"
    mv "$@" ${new_dir_name}
    echo 'Done!'
}
alias rm="move_to_trash"

相关内容