Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How can I make cp -r copy absolutely all of the files and directories in a directory

Requirements:

  • Include hidden files and hidden directories.
  • Be one single command with an flag to include the above.
  • Not need to rely on pattern matching at all.

My ugly, but working, hack is:

cp -r /etc/skel/* /home/user
cp -r /etc/skel/.[^.]* /home/user

How can I do this all in one command without the pattern matching? What flag do I need to use?

share|improve this question
    
More answers here, though they do not look as good; serverfault.com/questions/3154/… – Roel Van de Paar Jun 1 at 8:43
    
Please, Eleven81, consider changing the accepted answer to that given by @bruno pereira, because it avoids creating a new folder. If not, let this comment be a warning to new readers to check also the other (most voted) answer. Tx. – Dr Beco Jul 12 at 20:27

10 Answers 10

up vote 132 down vote accepted

Don't specify the files:

cp -r /etc/skel /home/user

(Note that /home/user must not exist already, or else it will create /home/user/skel.)

share|improve this answer
25  
Is it possible to use something similar if /home/user/skel does exist? – bradley.ayers Aug 24 '11 at 2:10
    
@bradley.ayers I think one could copy into a temporary subdirectory then move them to the upper level (since moving in the same drive is fast). Less than ideal, but shorter than other solutions to me. – Halil Özgür Mar 16 '13 at 9:58
5  
@bradley.ayers Bruno's answer below addresses your question – Mark Aug 20 '13 at 15:38
    
This solution didn't work for me. It did not copy hidden files. I'm using CentOS release 6.5. @Bruno's solution did the trick. – Technext Jan 29 at 13:02

Lets say you created the new folder (or are going to create one) and want to copy the files to it after the folder is created

mkdir /home/<new_user>
cp -r /etc/skel/. /home/<new_user>

This will copy all files/folder recursively from /etc/skel in to the already existing folder created on the first line.

share|improve this answer
9  
Works well for me. Note that the '.' is critical to it working. – Mark Aug 20 '13 at 15:39
23  
This is the best and most correct answer, should be the accepted one. – thnee Oct 14 '13 at 15:11
8  
It works, but, why ? Can't find a reference to this in the manual. – Julien Palard Jan 14 '14 at 13:37
3  
I think it works because normally, this would create a new folder with the name of the last folder in the first argument. However, since that name is ., this behavior would require it to create an already-existing directory, so it just skips that step. – Zenexer Jun 11 '14 at 20:07
3  
@Technext The default globbing in bash does not include filenames starting with a ., to change that you need to use the shopt -s dotglob command before to be able to include those files. So with *, by default, you are asking to copy all files recursively from this directory that can be expanded using * (which does not include hidden files by default). While on the other end with . you are using cp to recursively copy everything from "this directory". – Bruno Pereira Feb 1 at 20:39

bash itself has a good solution, it has a shell option, You can cp, mv and so on.:

shopt -s dotglob # for considering dot files (turn on dot files)

and

shopt -u dotglob # for don't considering dot files (turn off dot files)

above solution standards of bash

NOTE:

shopt # without argument show status of all shell options
-u # abbrivation of unset 
-s # abbrivation of set
share|improve this answer
1  
That's usefull when you want to copy just content without creating new directory inside destination. Especially when destination dir is mount point. – kaszynek Nov 11 '13 at 12:27
2  
This really is the best answer and gets to the heart of the question.. – Stephen May 23 '14 at 16:51
3  
It's setopt for zsh, in case anyone else is wondering. – Pat Dec 29 '14 at 23:18

Use rsync:

rsync -rtv source_folder/ destination_folder/

share|improve this answer

The correct means of doing this is to use the -T (--no-target-directory) option, and recursively copy the folders (without trailing slashes, asterisks, etc.), i.e.:

cp -rT /etc/skel /home/user

This will copy the contents of /etc/skel to /home/user (including hidden files), creating the folder /home/user if it does not exist; however the -T option prevents the contents of /etc/skel from being copied to a new folder /home/user/skel should the folder /home/user exist.

share|improve this answer

If your source and target directory have the same name, even if target directory exists, you can simply type:

cp -R /etc/skel /home/

This will copy the /etc/skel directory into /home/, including hidden files and directories.

Eventually, you can copy the directory and rename it in a single line :

cp -R /etc/skel /home/ && mv /home/skel /home/user
share|improve this answer
    
Or you could simply use cp -r /etc/skel /home/user for renaming skel to user... – David Sep 13 '13 at 12:46
    
That's right, only if /home/user does not exist yet. – Gabriel Hautclocq Oct 14 '13 at 11:52

Note that there is a command-line trick (works in, at least, sh, bash, and ksh): Just suffix the from directory with a slash. This will pour the contents of the from directory into the to directory (ironically, I had first learned about this trick when using rsync).

Example:

/tmp$ mkdir test_dir1
/tmp$ cd test_dir1/
/tmp/test_dir1$ touch aa
/tmp/test_dir1$ touch .bb
/tmp/test_dir1$ cd ..
/tmp$ mkdir test_dir2

/tmp$ cp -r test_dir1/* test_dir2
/tmp$ ls -1a test_dir2
.
..
aa

/tmp$ cp -r test_dir1/ test_dir2
/tmp$ ls -1a test_dir2
.
..
.bb
aa
share|improve this answer

rsync is good, but another choice:

cp -a src/ dst/

From the main help:

   -a, --archive
          same as -dR --preserve=all

   -d     same as --no-dereference --preserve=links

   -R, -r, --recursive
          copy directories recursively
share|improve this answer

I came here having Googled for a solution to the same problem, then I realized that it's easy to do with find. The advantage it doesn't depend on the shell, or special utilities that may not be installed.

find /etc/skel/ -mindepth 1 -exec cp -r {} /home/username/ \;

I tried the trick with trailing slash, but that didn't work for me.

share|improve this answer

You could use rsync.

rsync -aP ./from/dir/ /some/other/directory/

You can even copy over ssh

rsync -aP ./from/dir/ username@remotehost:/some/other/directory/

There are various flags you can use: -a, --archive # archive (-rlptgoD)

-r, --recursive
-l, --links      # copy symlinks as links
-p, --perms      # preserve permissions
-t, --times      # preserve times
-g, --group      # preserve group
-o, --owner      # preserve owner
-D               # --devices --specials

--delete         # Delete extra files

You may want to add the -P option to your command.

--partial        # By default, rsync will delete any partially transferred file if the transfer is interrupted. In some circumstances it is more desirable to keep partially transferred files. Using the --partial option tells rsync to keep the partial file which should make a subsequent transfer of the rest of the file much faster.

-P               # The -P option is equivalent to --partial --progress.   Its  purpose  is to make it much easier to specify these two options for a long transfer that may be interrupted.

Rsync man page

share|improve this answer

You must log in to answer this question.

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