18

Given that zsh can clobber all files given the command:

>*

I'm thinking that setting the option noclobber would be a good idea.

I can always use >| file if I want to use the default clobber behaviour in both bash and zsh. (zsh also allows the alternative syntax >!file).

I'm guessing noclobber is unset by default because of POSIX compatibility, but just to be sure:

Are there any downsides to setting noclobber?

Is there anyway to set noclobber only for the interactive shell?

  • 3
    I'm surprised zsh doesn't at least warn about that, given that it does warn about something like rm *... – ilkkachu Jul 1 '18 at 10:23
21

The reason noclobber is not set by default is tradition. As a matter of user interface design, it's a good idea to make “create this new file” the easy action and to put an extra hurdle the more dangerous action “either create a new file or overwrite an existing file”. Thus noclobber is a good idea (> to create a new file, >| to potentially overwrite an existing file) and it would likely have been the default if the shell had been designed a few decades later.

I strongly recommend to use the following in your interactive shell startup file (.bashrc or .zshrc):

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

In each case (redirection, copying, moving), the goal is to add an extra hurdle when the operation may have the side effect of erasing some existing data, even though erasing existing data is not the primary goal of the operation. I don't put rm -i in this list because erasing data is the primary goal of rm.

Do note that noclobber and -i are safety nets. If they trigger, you've done something wrong. So don't use them as an excuse to not check what you're overwriting! The point is that you should have checked that the output file doesn't exist. If you're told file exists: foo or overwrite 'foo'?, it means you made a mistake and you should feel bad and be more careful. In particular, don't get into the habit of saying y if prompted to overwrite (arguably, the aliases should be alias cp='yes n | cp -i' mv='yes n | mv -i', but pressing Ctrl+C makes the output look better): if you did mean to overwrite, cancel the command, move or remove the output file, and run the command again.

It's also important not to get into the habit of triggering those safeties because if you do, one day you'll be on a machine which doesn't have your configuration, and you'll lose data because the protections you were counting on aren't there.

noclobber will only be set for interactive shells, since .bashrc or .zshrc is only read by interactive shells. Of course you shouldn't change shell options in a way that would affect scripts, since it could break those scripts.

  • 6
    rm has an option -I that I use and recommend: "prompt once before removing more than three files, or when removing recursively; less intrusive than -i, while still giving protection against most mistakes" – Reid Jul 1 '18 at 15:19
  • 7
    I strongly recommend not re-aliasing cp and mv that way. However, using -i as a default argument to them is an excellent idea, but it should be applied at different alias names, not the originals (for instance I always put alias copy="cp -i" and alias move="mv -i" in my .bashrc). Why? Because of failure mode. What happens when you use a machine or different user that does not have the cp/mv aliases? Files potentially overwritten unintentionally (possibly undetected!). Corresponding failure mode with copy/move alias: shell complains that it does not recognise the command. – hlovdal Jul 1 '18 at 18:55
  • 1
    There is also an additional failure mode for cp/mv alias: when writing a shell script someone that is used to cp="cp -i" alias could write a cp command incorrectly expecting it to behave like in an interactive mode because there is no name difference. In contrast, every time I write "copy somefile /some/where" I know that I use an alias and not the cp command directly. And even if I should put a copy into a shell file it would fail the same way as for shell with missing alias. – hlovdal Jul 1 '18 at 18:56
  • 1
    So TL;DR the advice to default to use the -i argument for cp and mv is excellent, but the advice to reuse the cp and mv names is horribly bad. It is so bad I have to give the answer a down vote. Please change to use different alias names and I will give it an up vote. – hlovdal Jul 1 '18 at 18:57
  • 1
    @TomHale You could use alias RM='command rm', which would tell zsh to use the external command rm instead of the alias. That way you do not have to rely on --interactive=never superseding a previous -i. – Adaephon Jul 2 '18 at 14:13
6

Setting the noclobber shell option in ~/.bashrc (for bash) or ~/.zshrc (or more precisely $ZDOTDIR/.zshrc, for zsh) will make it active in interactive shell sessions.

Non-interactive shells (scripts) do not read these files.

Shell options are not normally inherited from parent shells.

This means that you should be able to set the option in those files without modifying the behaviour in existing scripts, unless scripts explicitly sources those files.

The only downside of doing this that I can see is that you will repeatedly forget that you have set the option, at least in the beginning. Later, as with all these kind of things, you will start to habitually use >|, even in cases where you actually might not want to clobber the file (just like people with aliases for rm, cp and mv with the -i option always set, eventually start to always use -f on the command line).

  • 2
    With bash, options are inherited if $SHELLOPTS ($BASHOPTS for the shopt ones) is in the environment (not something you'd generally want to do though for this kind of reason). – Stéphane Chazelas Jul 1 '18 at 13:05
2

The downside is that, if you become used to having noclobber active, you will one day use a system where it it not active and you will blithely execute a potentially-dangerous command, expecting the noclobber to save you... and it won't. And then you'll have to hope that there's a recent-enough backup to recover the data you destroyed because you assumed you would be asked for confirmation first.

  • Sure, one day you'll use a system where it isn't active. When you're using an unfamiliar system, you should be especially careful and ensure that the backups are up-to-date before doing anything potentially destructive like redirecting output to a file. – Gilles Jul 1 '18 at 20:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.