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.

How do you copy all the contents of one directory into another?

For example:

$ cd /home/newuser
$ cp -a /backup/olduser/* .

The problem with the above is that the globing pattern '*' matches the hidden directories '.' and '..' and you end up with a directory 'olduser' inside 'newuser', as well as the contents.

You could also do something like this:

$ rmdir /home/newuser
$ cp -a /backup/olduser /home/newuser

But what if newuser already contains some default files and directories?

What is the simplest, most correct, easiest to remember and not mess-up way to move the contents of one directory to another using just the basic 'cp' command and the shell?

share|improve this question
add comment

7 Answers

Two directories a and b.

Both have files in.

You are in a directory that contains a and b.

cp -r ./a b

-r = recursively.

share|improve this answer
    
Don't you want -a to get all files? –  bill weaver Aug 20 '09 at 17:22
4  
The -a argument is nothing do to with all files, it's short for archive, it will preserve file ownership, permissions, access times etc. The -a argument (while highly useful) isn't a standard option, and several cp implementations don't provide it. –  theotherreceive Aug 21 '09 at 3:26
1  
@mch: automatically included, because you've told cp to copy a directory a, and a/.somedotfile is contained by a. if b exists, this command will create an exact copy of a at b/a. –  quack quixote Nov 8 '09 at 0:33
2  
Easy way: cp -R /some/dir/* /another/dir –  MaxMackie Jul 4 '11 at 20:51
1  
This copies a/foo to b/a/foo instead of to b/foo –  Sparr Jul 30 '12 at 15:48
show 3 more comments

Try:

cp -ra /backup/olduser/. /home/newuser
share|improve this answer
    
This is great, but I can't figure out exactly how it works. I think it's probably because I don't understand how . and .. work. Care to explain? –  bradley.ayers Aug 24 '11 at 2:33
    
This worked for me but cp -r ./a b didn't. Any idea why? –  Brig Feb 21 '12 at 19:07
    
works for me too, but the r option is not needed. The a option implies r. –  MountainX Apr 14 '12 at 17:38
    
the -r parameter seems to be a bit redundant at this point! –  Master of Celebration Sep 12 '13 at 13:56
add comment

Also remember that by default cp copy the first directory INTO the second directory if the second exists. For example cp -a a b will copy a INTO b if b exists, i.e. it will create a into b.

If it's not what you want, and you want to copy the content of a into b (for example when copying a whole filesystem into a mount point) use:

cp -a a/. b

as in the previous answer.

Please also note that -a includes -r so -ar is redundant.

share|improve this answer
    
How does the /. work? –  bradley.ayers Aug 24 '11 at 2:54
    
a/. represents the content of directory 'a' as opposed to the directory itself, in most situation it is synonymous but when using cp -r, it avoids cp default behaviour (copying a INTO b). –  Nicolas Bonnefon Oct 20 '11 at 11:19
    
awesome tip, this is exactly what I was looking for but failed to find elsewhere - all that 'foo/*' or '-r foo/' that fails in corner cases. –  Tener Jun 1 '13 at 16:46
    
@TimoHuovinen '.' is not a wildcard at all. It is literally the "parent" directory, and '..' is the grandparent. This means '/foo/./././././.' is the same directory as '/foo', and '/foo/bar/..' is the same directory as '/foo'. Think of them as hardlinks that are builtin to the filesystem. –  quuxman Jun 20 at 10:57
    
@quuxman thank you, I wasn't aware of it back then. I'm gonna remove my old comment to avoid confusing people. –  Timo Huovinen Jun 20 at 19:35
add comment

Unless you have seriously reconfigured your shell, the globbing pattern '*' does not match '.' or '..', as you can verify using just echo *. What it does instead do is omit files whose name begins with a '.', so your approach will miss all hidden files. You can tweak some of this behavior with shell options, for example the dotglob option in bash, but it then won't be the portable and robust option that you are looking for.

If you need to do this more than once or twice, I recommend that you look into rsync or unison (depending on specific needs) with carefully crafted source and target specifications.

Another alternative is to put the source directory in a tarball and untar it over the existing target directory.

share|improve this answer
1  
i use this: ( cd /src/dir ; tar cf - . ) | ( cd /dest/dir ; tar xf - ) ... the tar cf - . tar's the source directory, dotfiles included, and spits it to STDOUT, which gets piped to the STDIN of the tar xf -. –  quack quixote Nov 8 '09 at 0:37
    
I think the whole point of the OP is how to reference files that start with '.' but not the special '.' and '..' directories. There is a far more elegant solution above instead of using rsync or some other complex program. –  quuxman Jun 20 at 10:59
add comment

This will copy both the normal and hidden files, while excluding the parent directory (..):

cd /directory/to/copy
cp -r * .[^.]* /destination/directory

If you do not exclude the parent directory, you end up with all of the contents of .. in your destination directory as well.

share|improve this answer
add comment

This works for copying all the files and directories except for hidden directories recursively from the current directory to wherever:

cp -rf * ^.* 
share|improve this answer
add comment

To copy files that begins with a dot just do cp .* target/

So easiest is just to do the cp command two times.

As Peter Eisentraut sais normal globbing rules do not include .. and . (hm, how to end this sentence? ;)

Just use -r to make it recursive and -i to make cp ask whether you really want to overwrite a file.

cp -ri /backup/olduser/* /newuser/
cp -ri /backup/olduser/.* /newuser/
share|improve this answer
    
Usually * does not match . or .., but it does if you use .*. Try echo .*. You can exclude . and .. with the following pattern: .[^.]*. –  mch Nov 7 '09 at 21:52
add comment

Your Answer

 
discard

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