20

I want to cp aaa/deep/sea/blob.psd to bbb/deep/sea/blob.psd

How do I do the copy if the deep and sea directories don't exist under bbb so that the copy both creates the directories that are needed and copies the file?

Right now I get
No such file or directory as deep and sea don't exist.

I looked thru the man help pages and other questions but nothing jumps out at me.

The closest I've got is using rcp for the directory:

rcp -r aaa/deep/sea/ bbb/deep/sea/

though this copies the whole directory and contents and I just want the one file. Trying to do that however gave cp: cannot create regular file bbb/deep/sea/blob.psd' such file or directory

0

5 Answers 5

24

It's easy using the install program from the coreutils that is typically used for this very purpose by build systems like automake:

install -D /path/to/source /path/to/destination

Note that install creates all parts of the path just like mkdir -p does, see man install. I'm curious why you didn't include why you want to do that. Calling mkdir and cp is very easy.

3
  • 2
    I think there are a lot of good answers on this question, but this one gets my vote as it's the most portable. The rsync answer will only create 1 directory, and pax doesn't seem to be common.
    – phemmer
    May 6, 2014 at 19:48
  • Use -d instead of -D on a Mac.
    – Matt M.
    Nov 14, 2016 at 23:01
  • note that this command creates the destination files with 755 (rwxr-xr-x) permissions, which is probably not desired. you can specify something else with the -m switch, but I could not find a way to just keep the file permissions :( Jan 9, 2019 at 19:19
19

Try to use such next function for such situation:

copy_wdir() { mkdir -p -- "$(dirname -- "$2")" && cp -- "$1" "$2" ; }

and use it as

copy_wdir aaa/deep/sea/blob.psd bbb/deep/sea/blob.psd

By the way, GNU cp has a --parents option. It's really close to what you want, but not exactly.
It will also create aaa directory that seems you don't need. However you can first cd to aaa and copy like:

cd aaa && cp --parents deep/sea/blob.psd ../bbb/
6

With standard (POSIX/Unix) commands, you've got:

pax -rws ':^:dest/dir/:' file .
2
  • 1
    Interesting. I'd never heard of pax before. Though I like its concept. Unfortunately even though it's in POSIX, it seems very few distros install it by default :-(
    – phemmer
    May 6, 2014 at 19:41
  • @Patrick - if you skip all the way to the end of info tar - somewhere around the portability concerns section - i think youll find that GNU tar claims to be fully pax compatible. I did anyway, though i have never yet got around to putting those claims to a test.
    – mikeserv
    Oct 9, 2014 at 6:01
5

I'm not aware of a way of doing it using cp, but it's certainly possible using rsync:

$ rsync sourcefile dir/

where dir is a directory that does not have to exist. There are lots of other ways of achieving the same using other commands.

4
  • 3
    You need rsync -R to preserve the directory heirarchy May 6, 2014 at 19:59
  • @glennjackman Indeed, 'proper' use of rsync needs more options, but the question was simply about creating a non-existent target directory, hence my brief answer :)
    – mjturner
    May 6, 2014 at 20:10
  • 1
    At least the GNU cp has the --parents option.
    – peterph
    May 6, 2014 at 20:45
  • 2
    @peterph Indeed, but then you're restricted in the naming of the target directory
    – mjturner
    May 7, 2014 at 7:49
4
cd aaa
pax -rw deep/sea/blob.psd ../bbb

If you don't have pax (it's mandated by POSIX, as a standard replacement of cpio and tar which had too many incompatibilities to standardize), use cpio -p or tar -cf - … | tar -xf - instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.