Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I find myself doing this often enough that I wonder if there's a standard Unix way to do it:

% mkdir -p /TARGETDIR/relative/path/to
% cp ./relative/path/to/somefile /TARGETDIR/relative/path/to

In other words, I don't want to just copy somefile to /TARGETDIR, but actually I want to copy its entire relative path.

Is there a simpler way to do this than the two-liner above?

share|improve this question
1  
you could use rsync to "mirror" one directory/filesystem to the other (including structure) –  h3rrmiller Mar 5 '13 at 20:15
    
@h3rrmiller How do you propose to do that (in a way that isn't cp -R relative /TARGETDIR)? –  Gilles Mar 5 '13 at 23:29
add comment

2 Answers 2

up vote 3 down vote accepted

With GNU coreutils (non-embedded Linux, Cygwin):

cp -p --parents path/to/somefile /TARGETDIR

With the POSIX tool pax (which many default installations of Linux unfortunately lack):

pax -rw -pp relative/path/to/somefile /TARGETDIR

With its traditional counterpart cpio:

find relative/path/to/somefile | cpio -p -dm /TARGETDIR

(This last command assumes that file names don't contain newlines; if the file names may be chosen by an attacker, use some other method, or use find … -print0 | cpio -0 … if available.)

Alternatively, you could make it a shell script or function.

cp_relpath () {
  mkdir -p -- "$2/$(dirname -- "$1")"
  cp -Rp -- "$1" "$2/$(dirname -- "$1")"
}
share|improve this answer
    
I'd say that cp's -p is irrelevant to the matter of the question (as well as writing scripts/programs is obviously redundant — actually I'm tempting to see another "answer" with version in Fortran, Cobol and Haskel, may be). –  poige Mar 6 '13 at 13:34
    
@poige It isn't, but usually the option is desirable, so I include it by default. –  Gilles Mar 6 '13 at 13:36
    
"Usually" != "really needed in question" –  poige Mar 6 '13 at 13:37
    
So, to conclude — the only difference between our answers really worth mentioning was pax "which many default installations of Linux unfortunately lack". Entropy thanks you, чо. –  poige Mar 6 '13 at 13:41
    
@poige Besides cp --parents, I wanted to mention pax and cpio for the non-Linux audience, and show how to do it with a function. –  Gilles Mar 6 '13 at 15:47
show 5 more comments

man cp reveals --parents. So simple, yeah.

$ mkdir /tmp/myetc && cp --parents init.d/cron /tmp/myetc && find /tmp/myetc/
/tmp/myetc/
/tmp/myetc/init.d
/tmp/myetc/init.d/cron
share|improve this answer
1  
Note that --parents is a GNUism (it is only a long version flag). –  vonbrand Mar 5 '13 at 22:13
    
@vonbrand, thanks, CO. –  poige Mar 5 '13 at 22:26
add comment

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.