4

I'd like to use cp -b to copy a file to a destination, possibly creating a backup file of the destination path if it already exists. But, if the backup file already exists, I'd like to have cp fail with an error.

I know I can use -n to avoid clobbering the target file, but I want to instead refuse to clobber the backup file.

Is there a way to do that? I happen to be using GNU cp on Linux, and I'm willing to accept an answer that is specific to Linux if no POSIX option is available.

9
  • 3
    cp doesn't have to clobber backups. Use ` cp --backup=t` and it will create numbered backups with no clobbering.
    – John1024
    Commented Jul 15, 2016 at 17:28
  • 1
    what is the difference between “avoid clobbering” and “refuse to clobber”? Commented Jul 15, 2016 at 18:08
  • 1
    @richard It's not a semantic difference between "avoid clobbering" and "refuse to clobber"... it's a difference of which file I'm trying not to clobber. In my case, it's the backup file, not the target file. The target file already has an option not-to-clobber. The backup file does not appear to have such an option. Commented Jul 15, 2016 at 19:12
  • 1
    @richard John posted the exact answer I was looking for, as a comment. If he posts it as an answer, I'll upvote + accept it. Commented Jul 15, 2016 at 20:02
  • 1
    Note that no POSIX solution can be available, since there is no -b option. This is specific to GNU coreutils.
    – Fox
    Commented Jul 15, 2016 at 21:38

2 Answers 2

6

If you want to avoid clobbering any backup files with GNU cp, you can use numbered backups:

cp --backup=t  source destination

Rather than overwrite a backup, this creates additional backups.

Example

As an example, let's consider a directory with two files:

$ ls
file1  file2

Now, let's copy file1 over file2:

$ cp --backup=t file1 file2
$ ls
file1  file2  file2.~1~

As we can see, a backup was made.

Let's copy it again:

$ cp --backup=t file1 file2
$ ls
file1  file2  file2.~1~  file2.~2~

Another backup was made.

Documentation

From man cp, just before the end of the "description" section, the various possible options for --backup are itemized:

The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX. The version control method may be selected via the --backup option or through the VERSION_CONTROL environment variable. Here are the values:

none, off
     never make backups (even if --backup is given)

numbered, t
     make numbered backups

existing, nil
     numbered if numbered backups exist, simple otherwise

simple, never
     always make simple backups

As a special case, cp makes a backup of SOURCE when the force and backup options are given and SOURCE and DEST are the same name for an existing, regular file.

0

If you always use this to copy only one file, you can create a shell function, possibly in your ~/.bashrc like

cpb () 
{ 
    if [ -r "${2}/${1}~" ] ; then 
        echo "backup of '$1' exists in '$2'"
    else 
        cp -b "$1" "$2"
    fi
}

and use it like this:

$ mkdir dir
$ cpb x dir
$ cpb x dir
$ cpb x dir
backup of 'x' exists in 'dir'
$ ls -l dir
insgesamt 0
-rw-r--r-- 1 ott ott 0 Jul 16 01:09 x
-rw-r--r-- 1 ott ott 0 Jul 16 01:08 x~

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .