Copy files with renaming
Many GNU tools such as cp
, mv
and tar
support creating backup files when the target exists. That is, when copying foo
to bar
, if there is already a file called bar
, the existing bar
will be renamed, and after the copy bar
will contain the contents of foo
. By default, bar
is renamed to bar~
, but the behavior can be modified:
# If a file foo exists in the target, then…
cp -r --backup source target # rename foo → foo~
cp -r --backup=t source target # rename foo → foo.~1~ (or foo.~2~, etc)
There are other variants, such as creating numbered backups only when one already exists. See the coreutils manual for more details.
I tried
apropos copy | grep "(1)"
to find possible candidates, and mcopy showed up.
man mcopy
shows a promising option -D clash-option
isn't that cool? But not so cool - it isn't described. But there are some hints to mtools.dvi, which I searched on my system, without success, and via google, without success, but then, with google, I searched directly for mcopy clash-option
and found this site.
I made a short test
mcopy -D A f* a
to tests for autorename and targetdir a
- instead of autorenaming it asked me for every file to ignore or override, that stupid s... .
My version is mtools-4.0.10
and the help page is from 1996 - 15 years old. Should we really lost some features, meanwhile?
I would split the work into two steps:
- Make a short function, which generates a unique name for a file, if that name is occupied.
- Run
find
, and execute that script for every file you wish to copy.
Shall we assist in this approach? :)
Here is a script, to autorename files:
#!/bin/bash
name=$1
target=$2
autorename () {
name=$1
target=$2
no=$3
test -e ${target}/${name}.$no && autorename ${name} ${target} $((no+1)) || cp ${name} ${target}/${name}.$no
}
test -e ${target}/${name} && autorename ${name} ${target} 0 || cp ${name} ${target}
and this is my test invocation:
find -maxdepth 1 -name "fo*" -type f -exec ./autorename.sh {} /mnt/hidden/test/a ";"
Note: -maxdepth, -name and -type where used to restrict the number of affected files dramatically. I didn't test the script for deeper file structures, nor for blanks in filenames and other, funky characters like linefeed, pagefeed and so on.
I used .1 because it doesn't make trouble in most commands, while a ( and a ) often need masking.