Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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

10 Answers 10

up vote 123 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
24  
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
4  
@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
7  
Works well for me. Note that the '.' is critical to it working. – Mark Aug 20 '13 at 15:39
20  
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
2  
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

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.