697

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?

Cfinley
  • 1,435
eleven81
  • 16,182

17 Answers17

785

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.

429

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

300

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.

TechnocratiK
  • 3,101
84

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
40

Use rsync:

rsync -rtv source_folder/ destination_folder/
  • r for recursive copying of directories
  • t for preserving modification times
  • v for increased verbosity
simhumileco
  • 697
  • 1
  • 7
  • 14
10

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
Excellll
  • 12,847
6

In my opinion, the simplest solution is:

cp -r /etc/skel/. /home/user

The current directory . at the end of /etc/skel/. combined with the -r flag, recursively copies all files, including hidden files and directories, to the target directory, but avoids copying directories . and .. because they are specific to the current directory and are not included when copying the contents.

It turned out that my previous solutions contained significant bugs (thanks to @DJCrashdummy and @GabrielDevenyi):

Even though the expression {.,}* includes all files and directories (also starting with a dot)..., unfortunately, this solution, can indeed cause issues by including . and .., leading to unwanted recursion:

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

And my original solution did not include files and subfolders starting with dots:

cp -r /etc/skel/* /home/user
simhumileco
  • 697
  • 1
  • 7
  • 14
6

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.

Mureinik
  • 4,152
Linus
  • 61
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
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

RoshP
  • 49
3

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.

3

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.

casimir
  • 39
3
cp -r /etc/skel/. /home/user/

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

WoJ
  • 3,875
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
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
0

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