Tom Hale Asked: 2018-07-02 00:01:59 +0800 CST2018-07-02 00:01:59 +0800 CST 2018-07-02 00:01:59 +0800 CST 设置 `noclobber` 有什么缺点吗? 772 鉴于zsh可以破坏给定命令的所有文件: >* 我认为设置选项noclobber将是一个好主意。 >| file如果我想在 bash 和 zsh 中使用默认的clobber 行为,我总是可以使用。(zsh 也允许替代语法>!file)。 我猜noclobber由于POSIX兼容性,默认情况下未设置,但为了确定: 设置有什么缺点noclobber吗? 无论如何noclobber只为交互式外壳设置? bash shell 4 个回答 Voted Best Answer Gilles 'SO- stop being evil' 2018-07-02T00:20:33+08:002018-07-02T00:20:33+08:00 默认情况下未设置的原因noclobber是传统。作为用户界面设计的问题,最好让“创建这个新文件”成为简单的操作,并为更危险的操作“创建新文件或覆盖现有文件”设置额外的障碍。这noclobber是一个好主意(>创建一个新文件,>|可能覆盖现有文件),如果外壳是在几十年后设计的,它可能是默认设置。 我强烈建议在您的交互式 shell 启动文件(.bashrc或.zshrc)中使用以下内容: set -o noclobber alias cp='cp -i' alias mv='mv -i' 在每种情况下(重定向、复制、移动),目标都是在操作可能具有擦除某些现有数据的副作用时增加额外的障碍,即使擦除现有数据不是操作的主要目标。我没有放在rm -i这个列表中,因为擦除数据是rm. 请注意noclobber和-i是安全网。如果他们触发,你做错了什么。因此,不要以它们为借口不检查您正在覆盖的内容!关键是您应该检查输出文件不存在。如果你被告知file exists: fooor overwrite 'foo'?,这意味着你犯了一个错误,你应该感到难过并更加小心。特别是,不要养成说y是否提示覆盖的习惯(可以说,别名应该是alias cp='yes n | cp -i' mv='yes n | mv -i',但按Ctrl+C会使输出看起来更好):如果您确实要覆盖,取消命令,移动或删除输出文件,然后再次运行该命令。 同样重要的是不要养成触发这些安全措施的习惯,因为如果你这样做了,有一天你会在一台没有你的配置的机器上,并且你会丢失数据,因为你所依赖的保护措施是'那里。 noclobber只会为交互式 shell 设置,因为.bashrcor.zshrc只能由交互式 shell 读取。当然,您不应该以影响脚本的方式更改 shell 选项,因为它可能会破坏这些脚本。 Dave Sherohman 2018-07-02T11:37:16+08:002018-07-02T11:37:16+08:00 不利的一面是,如果你习惯了noclobber活跃,你有一天会使用一个它不活跃的系统,你会愉快地执行一个潜在的危险命令,期望noclobber拯救你......但它不会。然后您将不得不希望有足够新的备份来恢复您破坏的数据,因为您假设您会首先被要求确认。 Kusalananda 2018-07-02T00:19:17+08:002018-07-02T00:19:17+08:00 在(for ) 或(或更准确地说, for ) 中设置noclobbershell 选项将使其在交互式 shell 会话中处于活动状态。~/.bashrcbash~/.zshrc$ZDOTDIR/.zshrczsh 非交互式 shell(脚本)不读取这些文件。 Shell 选项通常不会从父 shell 继承。 这意味着您应该能够在这些文件中设置该选项,而无需修改现有脚本中的行为,除非脚本明确来源这些文件。 我可以看到这样做的唯一缺点是你会反复忘记你已经设置了选项,至少在开始时是这样。稍后,与所有这些事情一样,您将开始习惯性地使用>|,即使在您实际上可能不想破坏文件的情况下(就像具有别名的人一样rm,cp并且始终mv设置-i选项,最终开始始终使用-f在命令行上)。 Akhil 2021-02-17T02:13:07+08:002021-02-17T02:13:07+08:00 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"
默认情况下未设置的原因
noclobber
是传统。作为用户界面设计的问题,最好让“创建这个新文件”成为简单的操作,并为更危险的操作“创建新文件或覆盖现有文件”设置额外的障碍。这noclobber
是一个好主意(>
创建一个新文件,>|
可能覆盖现有文件),如果外壳是在几十年后设计的,它可能是默认设置。我强烈建议在您的交互式 shell 启动文件(
.bashrc
或.zshrc
)中使用以下内容:在每种情况下(重定向、复制、移动),目标都是在操作可能具有擦除某些现有数据的副作用时增加额外的障碍,即使擦除现有数据不是操作的主要目标。我没有放在
rm -i
这个列表中,因为擦除数据是rm
.请注意
noclobber
和-i
是安全网。如果他们触发,你做错了什么。因此,不要以它们为借口不检查您正在覆盖的内容!关键是您应该检查输出文件不存在。如果你被告知file exists: foo
oroverwrite 'foo'?
,这意味着你犯了一个错误,你应该感到难过并更加小心。特别是,不要养成说y
是否提示覆盖的习惯(可以说,别名应该是alias cp='yes n | cp -i' mv='yes n | mv -i'
,但按Ctrl+C会使输出看起来更好):如果您确实要覆盖,取消命令,移动或删除输出文件,然后再次运行该命令。同样重要的是不要养成触发这些安全措施的习惯,因为如果你这样做了,有一天你会在一台没有你的配置的机器上,并且你会丢失数据,因为你所依赖的保护措施是'那里。
noclobber
只会为交互式 shell 设置,因为.bashrc
or.zshrc
只能由交互式 shell 读取。当然,您不应该以影响脚本的方式更改 shell 选项,因为它可能会破坏这些脚本。不利的一面是,如果你习惯了
noclobber
活跃,你有一天会使用一个它不活跃的系统,你会愉快地执行一个潜在的危险命令,期望noclobber
拯救你......但它不会。然后您将不得不希望有足够新的备份来恢复您破坏的数据,因为您假设您会首先被要求确认。在(for ) 或(或更准确地说, for ) 中设置
noclobber
shell 选项将使其在交互式 shell 会话中处于活动状态。~/.bashrc
bash
~/.zshrc
$ZDOTDIR/.zshrc
zsh
非交互式 shell(脚本)不读取这些文件。
Shell 选项通常不会从父 shell 继承。
这意味着您应该能够在这些文件中设置该选项,而无需修改现有脚本中的行为,除非脚本明确来源这些文件。
我可以看到这样做的唯一缺点是你会反复忘记你已经设置了选项,至少在开始时是这样。稍后,与所有这些事情一样,您将开始习惯性地使用
>|
,即使在您实际上可能不想破坏文件的情况下(就像具有别名的人一样rm
,cp
并且始终mv
设置-i
选项,最终开始始终使用-f
在命令行上)。rm
我建议也为命令添加别名。我将接受的答案和我的建议结合起来使其变得简单。