Unix Power Tools
Copying Directory Trees with cp -r
by Jerry Peek
02/03/2000
Some versions of cp have a -r (recursive) flag.
It copies all the files in a directory
tree -- that is, all the files in a directory and its subdirectories.
The first argument(s) to cp -r can be directory(s) -
or, if you name any file(s), they'll be copied just the way they would
without the -r. The last argument should be a
directory. So, you can use cp -r in two
ways:
Give
cp -rdirectory(s) to copy. They'll be created as subdirectories of the directory named at the end.Give
cp -rfile(s) to copy. They'll be copied to the directory named at the end.
Those two methods are really doing the same thing. They're both copying the tail of the first pathname(s) to the end of the last pathname.
-
Here's how to do the copy shown in the figure below. This copies the directory
/home/jane, with all its files and subdirectories, and creates a subdirectory namedjanein the current directory (.) :% cd /work/bkup % cp -r /home/jane .
How can you copy the contents of the subdirectory called
dataand all its files (but not the subdirectory itself) into a duplicate directory nameddata.bak? First create the destination directory. That's because the last argument tocp -rmust be a directory that already exists:% cd /home/jane % mkdir data.bak % cp -r data/* data.bak
That doesn't copy any files in
datawhose names start with a dot (.).To copy the subdirectories
SepandOctand their files, as well as the fileOutput, from the directory/home/jim/calendarinto the current directory (.):% cp -r /home/jim/calendar/[SO]* .
If you use the C shell or
bash, you can copy just the directories by using the handy curly brace operators:% cp -r /home/jim/calendar/{Sep,Oct} .Some gotchas:
Symbolic and hard links are copied as files. That can be good because, at the destination, a symbolic link might point to the wrong place. It can be bad if the link pointed to a really big file; the copy can take a lot of disk space. (In the figure above, notice that the symbolic link in
jane's home directory was converted to a file named.setupwith a copy of the contents ofgeneric.)On many UNIXes, the copy will be dated at the time you made the copy and may have its permissions set by your umask. If you want the copy to have the original modification time and permissions, add the
-poption.cp -rwill go into an endless loop if you name a directory in the list to copy from and also as the destination directory. For example, let's say you're copying everything from the current directory into an existing subdirectory namedbackup, like this:% cp -r * backup
Unless your
cp -rworks differently from the ones I've tried, it will createbackup/backup, andbackup/backup/backup, and so on. To avoid that, replace the * wildcard with other less-"wild" wildcards. You can also match everything except the destination directory name by using the ksh ! operator, or the tcsh ^ operator.

Figure: Copying /home/jane to Current Directory (/work/bkup) with cp