Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I just started using BASH, so I can move all contents of a directory to another. But the issue is, I was expecting it to merge the directories. I am using cron job to run this script.

#!/bin/bash

shopt -s dotglob nullglob
mv mv_schedule/* public_html/

Source: /mv_schedule/ (containing folders/files)

/files/
4.html
5.html
/assets/
sitemap.xml

Destination: /public_html/ (previous folders already exist)

/files/
1.html
2.html
3.html
/assets/
sitemap.xml

So what I want, is for all of the new files from those directories inside /mv_schedule/ to merge with the ones in /public_html/, and for the files that already exist in there, to be replaced with the ones coming from /mv_schedule/.

It's currently returning this error via email when I try this with the current script:

mv: cannot move `mv_schedule/assets' to `public_html/assets': Directory not empty

How can I fix this?

share|improve this question
    
Are you running this bash script as root user or normal user ? if it is a root user then what is the output of alias -a / –  max Oct 9 '13 at 5:39
    
Unfortunately, I'm not sure. I'm only on cPanel of shared hosting, so I probably don't have true root access. –  The Bash Oct 9 '13 at 5:45
add comment

1 Answer

up vote 2 down vote accepted

What the error message is telling you is that it cannot mv the asset directory because there are files inside it. mv a directory means making a copy, then erasing it, and it cannot erase it because it still contains some files. This means you should mv the files inside asset as well, and even the subdirectories and files within subdirectories within asset, if they exist. But the mv command that issued can only copy (and the erase) what is present inside the mv_schedule directory, not what is present within the subdirectories (like asset) within mv_schedule.

What you want is a command that descends the directory tree down to the last leaf and copies it, something like a -r or -R option in rm, chmod, chown. However, mv has no such option, so you will have to use the command find, which descends the whole directory tree from a root you specify, and then executes an action you specify. In your case, a suitable command is:

SOURCE_DIR=$1
TARGET_DIR=$2
find $SOURCE_DIR -name '*' -type f -exec mv -f {} $TARGET_DIR \;

This will pile up all files into a single target directory. It assumes that you passed the source and target directory as input-line parameters to a bash script. The -f option prevents asking for confirmation in case of overwriting, you can change that to -n (do not overwrite) or -i (ask before overwriting).

If instead you wish to preserve the directory structure, remember that the command cp does have the ability to descend the directory tree, so that you may use that one, followed by a rm, since this command also has the ability to descend trees. One possible set of commands is:

SOURCE_DIR=$1
TARGET_DIR=$2
cp -a $SOURCE_DIR $TARGET_DIR
rm -rf $SOURCE_DIR

Notice the -a option in cp: it preserves timestamps and ownerships. If you do not care for such things, you can use -R instead.

share|improve this answer
    
I'm afraid I don't completely understand your answer. But I would place SOURCE_DIR and TARGET_DIR with dirName/? Also, I see you mentioned -i(ask before overwriting). I want it to overwrite existing files, and merge with existing directories, to keep all existing files in the destination directory and add(also replace existing files) the new ones from same name directory from source. –  The Bash Oct 9 '13 at 6:16
    
you can set SOURCE_DIR and TARGET_DIR to the values you want, in this case SOURCE_DIR=mv_schedule and then TARGET_DIR=public_html. You can overwrite with the -f option, but you have not clarified what you want to do with the files in, say, the directory asset. Should they go 1) inside the public_html directory, or should they go into the directory public_html/assets? The two options I have proposed do these two different things, respectively. –  MariusMatutiae Oct 9 '13 at 6:41
    
I added a couple of lines to my answer, trying to clarify it. –  MariusMatutiae Oct 9 '13 at 6:54
    
rm -rf $SOURCE_DIR will remove the source directory, perhaps it's better to preserve it and use rm -rf "$SOURCE_DIR/*" -- It's also advised to use quotes around variables (in case directory names have spaces) –  medigeek Oct 9 '13 at 7:07
    
Well, since I know it's not possible to use mv to simply move the files.. I'd like to leave the contents of the source directory intact. And to clarify again so everyone understands, it's 'only' the contents of /mv_schedule/, not the directory /mv_schedule/` itself. –  The Bash Oct 9 '13 at 8:01
show 4 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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