658

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?

3
  • 1
    More answers here, though they do not look as good; serverfault.com/questions/3154/… Jun 1, 2016 at 8:43
  • 2
    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.
    – DrBeco
    Jul 12, 2016 at 20:27
  • How about running shopt -u dotglob to include hidden files then run cp -rfv /etc/skel /home/user which will also show you progress in case you are copying a big directory. Apr 22, 2020 at 2:45

18 Answers 18

411

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.)

9
  • 96
    Is it possible to use something similar if /home/user/skel does exist? Aug 24, 2011 at 2:10
  • 9
    @bradley.ayers Bruno's answer below addresses your question
    – Mark
    Aug 20, 2013 at 15:38
  • 5
    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, 2016 at 13:02
  • 5
    Under ubuntu/debian this places the directory 'skel' inside target directory and not the recursed files inside skel. Use -T (no target) per below for proper use. (-rT for recursive)
    – B. Shea
    Jun 23, 2017 at 15:45
  • 25
    Answering a 7.5 year old question, you can run cp -r /etc/skel/. /home/user to avoid creating the subdirectory (note the /. following etc/skel).
    – carpeliam
    Mar 19, 2019 at 20:00
754

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.

19
  • 7
    If I didn't get it wrong, this didn't copy hidden/dot files. Mar 16, 2013 at 9:56
  • 81
    Works well for me. Note that the '.' is critical to it working.
    – Mark
    Aug 20, 2013 at 15:39
  • 18
    It works, but, why ? Can't find a reference to this in the manual. Jan 14, 2014 at 13:37
  • 7
    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, 2014 at 20:07
  • 62
    @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". Feb 1, 2016 at 20:39
275

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.

10
  • 22
    Correct answer. +1
    – B. Shea
    Jun 23, 2017 at 15:47
  • 7
    this is the BEST answer of the bunch; its the only one that solves the problem without complicating it
    – ZaxLofful
    Sep 12, 2018 at 18:25
  • 5
    Love it when you use the correct cmd flag for the one case.
    – Tran Triet
    Sep 11, 2019 at 3:59
  • 3
    Not supported on all versions of cp, alas, but great when it is there. Apr 27, 2020 at 14:55
  • 6
    Doesn't work on mac :( Sep 9, 2021 at 7:36
83

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 is standard of bash

NOTE:

shopt # without argument show status of all shell options
-u # abbrivation of unset 
-s # abbrivation of set
3
  • 2
    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, 2013 at 12:27
  • 11
    It's setopt for zsh, in case anyone else is wondering.
    – Pat
    Dec 29, 2014 at 23:18
  • This should be the accepted answer. Users shouldn't have to modify their workflows to account for the sins of Unix. Configuring your shell to act how you expect it to act is always a better solution.
    – Fopedush
    Mar 19 at 15:28
36

Use rsync:

rsync -rtv source_folder/ destination_folder/

1
  • Best option for me, although I use --progress to have more feedback on the whole process.
    – Edenshaw
    Jan 2, 2019 at 13:06
9

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
2
  • This answer is incorrect in terms of the original question asked (include hidden files): both cp -r as well as cp -a copy hidden files when cp ... src dst or cp ... src/ dst/ is used. It may be that this changed overtime. Sep 8, 2020 at 3:52
  • works like a charm.
    – Evan Hu
    Nov 19, 2022 at 7:19
7

The simplest way is:

cp -r /etc/skel/{.,}* /home/user

The expression {.,}* includes all files and directories (also starting with a dot).

If you don't want use above expression, then you can use the cp property, which is the ability to specify multiple sources for one target folder:

cp -r /etc/skel/* /home/user
4
  • 2
    this would miss files like ..anything or ...anything etc. - stackoverflow.com/a/31438355/2351568 contains the correct regex for this problem. || but anyway using shopt -s dotglob is still the better solution! Sep 6, 2018 at 17:53
  • @DJCrashdummy unfortunately, I do not understand why you wrote your attention. After all, my solution takes into account the cases you write about. Regards Sep 6, 2018 at 22:30
  • 2
    sorry wrong text! - the problem with your answer is, that it will also consider . and .. (which is equivalent to the current and its containing folder). || but still the answer in the link explains it further and provides a solution. Sep 7, 2018 at 16:23
  • This answer is very wrong as it actually recuses UP the file tree! Mar 16, 2023 at 14:32
5

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
2
  • Or you could simply use cp -r /etc/skel /home/user for renaming skel to user...
    – David
    Sep 13, 2013 at 12:46
  • That's right, only if /home/user does not exist yet. Oct 14, 2013 at 11:52
5

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.

1
  • This also lets you exclude some files/directories with exclusion filters (e.g. ! -name 'dontcopythis') which might be handy.
    – FK82
    Oct 8, 2021 at 15:13
4

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

3

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
2

My solution for this problem when I have to copy all the files (including . files) to a target directory retaining the permissions is: (overwrite if already exists)

yes | cp -rvp /source/directory /destination/directory/

yes is for automatically overwriting destination files, r recursive, v verbose, p retain permissions.

Notice that the source path is not ending with a / (so all the files/directory and . files are copied)

Destination directory ends with / as we are placing contents of the source folder to destination as a whole.

2

You can copy the content of a folder /source to another existing folder /dest, including hidden files, with the command:

$ cp -a /source/. /dest/

The -a option is an improved recursive option, that preserve all file attributes, and also preserve symlinks.

The . at end of the source path is a specific cp syntax that allowes to copy all files and folders, including hidden ones.

2
  • Avoid posting answers to old questions that already have well received answers unless you have something substantial and new to add.
    – Toto
    Sep 16, 2022 at 8:22
  • Agree with @Toto - Your answer is the same as that of @BrunoPereira's answer which was posted 11 years ago and already has nearly 700 upvotes. I know there are a lot of answers here to read through before posting yours, but please do it. There's just no sense in adding yet answer to the long list (currently 20) unless you truly have something new and useful to add. It just makes it even more difficult for the next user to find the existing answer. Thanks! Nov 24, 2022 at 2:01
2
cp -r /etc/skel/. /home/user/

The slash (/) after "user" does make a difference.

1
  • 1
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Feb 9, 2023 at 19:15
1

I have seen that cp does not always copy hidden files and if you would like an command that seems to work across all linux/unix dialects you should try using:

cd /etc/skel
find | cpio -pdumv /home/user
-2

To copy files, directories and hidden files from a directory to existing/new directory:

cp -a /etc/skel /home/user

Copy to current directory:

cp -a /etc/skel/. .
-2

ignore error

cp -r asdf/* qwer/
cp -r asdf/.[^.]* qwer/ 2>/dev/null | true
1
  • Avoid posting answers to old questions that already have well received answers unless you have something substantial and new to add.
    – Toto
    Jan 4, 2023 at 17:19
-3

As of at least K3b 2.0.3, there is a question box that pops up when the directory is added to the project, that ask if you want to include hidden files ... there is also a question that pops up to ask about including links. Nice stuff!

1

You must log in to answer this question.

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