2

When trying to move some folder I am getting error: "cannot move File exists"

export BACKUP_DIR=/backup
mv -f $BACKUP_DIR/scripts $BACKUP_DIR/scripts_old

Getting error:

mv: cannot move '/backup/scripts' to '/backup/scripts_old/scripts': File exists

I've tried with -f option but without it as well - same error. How I can move this?

Thanks!

AndreyS
  • 248
  • 1
    @they scripts_old is folder and it contains as well folder scripts which I want to overwrite drwxr-xr-x. scripts_old – AndreyS Jan 16 '22 at 20:13
  • Sorry, I did not spot that this was already mentioned in the error message that you quoted. – Kusalananda Jan 16 '22 at 20:17
  • Related - https://unix.stackexchange.com/q/228597/100397 – Chris Davies Jan 16 '22 at 20:25
  • @roaima I think it's not related!!!!!! -R option cannot be used for mv. output: mv: invalid option -- 'R' sorry but your link is not valid solution – AndreyS Jan 16 '22 at 20:28
  • I know it's not a valid solution, but it's definitely related. I'm just writing a full answer for you! – Chris Davies Jan 16 '22 at 20:29
  • Do you want to merge or overwrite as in "delete the old directory and contents then replace by new directory and contens"? – FelixJN Jan 16 '22 at 20:37
  • @FelixJN I would like to overwrite as that is the folder. So to put additional folder instead of the previous one but without introducing additional rm command before the mv – AndreyS Jan 16 '22 at 20:38
  • @FelixJN ok thanks a lot for your assistance – AndreyS Jan 16 '22 at 21:05

3 Answers3

4

You cannot merge existing directories with mv. The error message comes about because scripts already exists in /backup/scripts_old.

What you can do, though, is to copy/link the files across and then remove the linked files from the source. The solution here requires GNU (non-POSIX) cp and only works if the source and destination are on the same filesystem:

BACKUP_DIR=/backup
cp -al "$BACKUP_DIR"/scripts/. "$BACKUP_DIR"/scripts_old/scripts
find "$BACKUP_DIR"/scripts -type f -links 2 -print

Notes

  • The trailing dot (.) on the copy source is essential
  • Change -print to -delete when you're happy it's going to delete the correct files from the source
  • Double-quote your variables when you use them (otherwise directories with spaces in their name will break your code horribly)
  • If you don't have GNU cp with the option to create links instead of copies, then rsync or pax can suffice
Chris Davies
  • 116,213
  • 16
  • 160
  • 287
  • Thanks. Can you clarify why -al options are required? why is archive important and why do you want to create hard links instead of copying? I don't want to create hard links – AndreyS Jan 16 '22 at 20:41
  • Doesn't this also require that source and target be on the same file system? – terdon Jan 16 '22 at 20:50
  • According to the comments, OP is not interest in merging, but the equivalent of removing target and replacing it with source (without trace of the previous contents). – FelixJN Jan 16 '22 at 20:56
  • @FelixJN changing the requirements in comments? They haven't changed in the question. This is why it's so important to keep all the necessary information in one place. And answers shouldn't be in comments either – Chris Davies Jan 16 '22 at 22:17
  • Whether "move" should mean "merge" or "fully replace" can at least be argued and the original question allows for either interpretation - the question simply needs an update for more clarity. Agreed on my comment having gotten a bit out of hand - it didn't fulfill the "single command" requirement, but after all it is more of an answer than a comment. – FelixJN Jan 16 '22 at 23:00
3

The mv command does not support replacing directories, as this is a very dangerous operation. If you did this accidentally, you would lose all the data in the target directory.

If you don't want to merge the two folders, you will have to rename or delete the target folder $BACKUP_DIR/scripts_old/scripts before attempting the mv. This can't be bypassed.

Here are your options:

  • Delete the target directory first
  • Put the source directory into the target directory as $BACKUP_DIR/scripts_old/scripts/scripts
  • Rename either the source or target directory, e.g., $BACKUP_DIR/scripts_old/scripts1
  • merge the directories (but this might overwrite files or have additional directory collisions) mv scripts/* $BACKUP_DIR/scripts_old/scripts/* (or do something similar like the find in the other answer)
  • Use something like rsync to replace files in the target directory with files from the source directory, optionally deleting the source and optionally deleting things in the target not in the source (likely this is the slowest of the options)

You didn't really explain why you want a backup directory like this. Perhaps it would be better to not use a backup directory at all, but instead use a revision control tool like git.

user10489
  • 6,740
2

I think this cannot be done without a separate removal.

rsync allows to a) remove source files (but files only) via --remove-source-files and b) delete files in target that do not exist in source (--delete). Best to be used with -nv to make a verbose dry-run. Depending on the version of rsync, -recursivity may be needed.

Nevertheless this you will have the empty directory tree left in source and directories not mentioned in source will remain untouched in target.

Long story short: use two commands and the simples option would be:

rm "$BACKUP_DIR"/scripts_old &&
mv "$BACKUP_DIR"/scripts "$BACKUP_DIR"/scripts_old
FelixJN
  • 13,566