594

When copying a file using cp to a folder that may or may not exist, how do I get cp to create the folder if necessary? Here is what I have tried:

[root@file nutch-0.9]# cp -f urls-resume /nosuchdirectory/hi.txt
cp: cannot create regular file `/nosuchdirectory/hi.txt': No such file or directory
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
omg
  • 136,412
  • 142
  • 288
  • 348
  • 3
    @nelaar The age of the question is a secondary concern; the quality and breadth of the answers should be the deciding factor. I don't have a strong preference either way, but I don't think it's worth the effort at this point to turn around the duplicate relationship. If you think otherwise, please offer a rationale (perhaps on https://meta.stackoverflow.com/ for proper visibility and process). – tripleee Sep 28 '15 at 17:04
  • Looked for the same thing and could not find my answer below so will post how I ended up doing this: `dirname "/nosuchdirectory/hi.txt" | while read path;do mkdir -p "$path"; done && cp -f urls-resume /nosuchdirectory/hi.txt` – Greg0ry Nov 24 '16 at 19:58
  • See e.g. http://meta.stackoverflow.com/questions/251938/should-i-flag-a-question-as-duplicate-if-it-has-received-better-answers – tripleee Dec 19 '16 at 05:38

7 Answers7

380

To expand upon Christian's answer, the only reliable way to do this would be to combine mkdir and cp:

mkdir -p /foo/bar && cp myfile "$_"

As an aside, when you only need to create a single directory in an existing hierarchy, rsync can do it in one operation. I'm quite a fan of rsync as a much more versatile cp replacement, in fact:

rsync -a myfile /foo/bar/ # works if /foo exists but /foo/bar doesn't.  bar is created.
Neuron
  • 5,141
  • 5
  • 38
  • 59
lhunath
  • 120,288
  • 16
  • 68
  • 77
  • 8
    It's mentioned in the above answer but I'd like to re-emphasize it (after a few minutes wasted because of not noticing the fine print): The `rsync` command above is *not* equivalent to the `mkdir/cp` command above. It just creates a single level of folder. Actually I'm not sure when it can be useful. – Penghe Geng Apr 13 '15 at 14:30
  • 14
    Also, for anyone wondering about the `-p` argument to `mkdir`, it's documented in the POSIX standard at http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mkdir.html and causes intermediate pathname components to be created (i.e. lets you `mkdir foo/bar/baz` even if `foo` or `bar` don't already exist). – Mark Amery Sep 13 '15 at 21:52
  • 14
    `"$_"` is a `bash variable` - [LINK FOR MORE INFO](http://www.thegeekstuff.com/2010/05/bash-shell-special-parameters/#comments). – Aakash Feb 21 '17 at 05:00
  • 1
    Some more info about the bash variables: https://stackoverflow.com/a/5163260/3982562 – 3limin4t0r May 15 '18 at 15:58
  • 4
    @PengheGeng : yes, this rsync command can only create one level of folders, but rsync has options to create them all, or only some. [rsync: how can I configure it to create target directory on server?](https://stackoverflow.com/questions/1636889/) – mivk Aug 17 '18 at 11:30
  • 1
    what a chore.. this should be implemented for `cp` – lamino Oct 26 '18 at 00:11
  • rsync is so powerful that I suggest dry-run option. "rsync --dry-run -av myfile /foo/bar/". – Smile Nov 13 '19 at 13:29
  • Downvote: For those looking to automate, the `cp --parents` and `rarchive` answers may likely be better. This is because the `mkdir -p` part of this answer takes just a directory, requiring you to script an extra step to parse the directory out from the full filename. – Thomas W Oct 21 '21 at 22:38
133

I didn't know you could do that with cp.

You can do it with mkdir ..

mkdir -p /var/path/to/your/dir

EDIT See lhunath's answer for incorporating cp.

Community
  • 1
  • 1
Christian
  • 3,917
  • 2
  • 23
  • 40
  • 48
    cp(1) doesn't. mkdir -p /foo/bar && cp myfile "$_" is indeed the only way to do this reliably. – lhunath Jun 04 '09 at 05:53
  • Check this answer - http://stackoverflow.com/a/34608146/2007944 – SD. Jan 05 '16 at 09:27
  • This anwser should not be here. The question was regarding `cp` not `mkdir` ... – basickarl Aug 04 '17 at 07:58
  • Hi @KarlMorrison this is an 8 year old question & answer. I also stated that it was for mkdir and not cp. – Christian Aug 06 '17 at 07:08
  • @Christian I know, it is 2017 and this is the answer directly under the question, which it shouldn't be. I know that you stated that, however people like me actually looking for an answer regarding the `cp` command is met with answers like this which have nothing to do with `cp` prolonging my search for a correct answer. The only answer here which is accurate is https://stackoverflow.com/a/947971/1137669 he states that `cp` cannot do it. No one else (including yourself) state that it is not possible with `cp`. – basickarl Aug 07 '17 at 08:59
  • Doesn't `cp --parents {}` make it done now? – IC_ Dec 18 '18 at 11:29
  • For those looking to automate, the `cp --parents` and `rarchive` answers may likely be better. This is because the `mkdir -p` part of this answer takes just a directory, requiring you to script an extra step to parse the directory out from the full filename. – Thomas W Oct 21 '21 at 22:38
39

One can also use the command find:

find ./ -depth -print | cpio -pvd newdirpathname
oz123
  • 27,559
  • 27
  • 125
  • 187
Jeff King
  • 399
  • 3
  • 2
  • 1
    this is by far the best answer because it allows you to create directories without previously needing to know their full path. – Miguel Costa Oct 27 '21 at 20:59
36
 mkdir -p `dirname /nosuchdirectory/hi.txt` && cp -r urls-resume /nosuchdirectory/hi.txt
Jamie McCrindle
  • 9,114
  • 6
  • 43
  • 48
23

There is no such option. What you can do is to run mkdir -p before copying the file

I made a very cool script you can use to copy files in locations that doesn't exist

#!/bin/bash
if [ ! -d "$2" ]; then
    mkdir -p "$2"
fi
cp -R "$1" "$2"

Now just save it, give it permissions and run it using

./cp-improved SOURCE DEST

I put -R option but it's just a draft, I know it can be and you will improve it in many ways. Hope it helps you

victor hugo
  • 35,514
  • 12
  • 68
  • 79
  • 3
    Quote your parameter expansions, please. Or you'll suffer bugs introduced by wordsplitting and pathname expansion. Put "" around all your $foo's. – lhunath Jun 04 '09 at 05:50
  • 9
    That will lead to weird results if someone tries to rename the file while coping: `cp-improved /foo/file.jpg /bar/file.jpg.bak`. I will end up with `/bar/file.jpg.bak/file.jpg` regardless if `bar` exists or not – MestreLion Aug 05 '11 at 23:49
9

rsync is work!

#file:
rsync -aqz _vimrc ~/.vimrc

#directory:
rsync -aqz _vim/ ~/.vim
Chu-Siang Lai
  • 2,658
  • 1
  • 24
  • 21
-9
cp -Rvn /source/path/* /destination/path/
cp: /destination/path/any.zip: No such file or directory

It will create no existing paths in destination, if path have a source file inside. This dont create empty directories.

A moment ago i've seen xxxxxxxx: No such file or directory, because i run out of free space. without error message.

with ditto:

ditto -V /source/path/* /destination/path
ditto: /destination/path/any.zip: No space left on device

once freed space cp -Rvn /source/path/* /destination/path/ works as expected

pedro
  • 7