mkdir -p will create a directory; it will also make parent directories as needed.

Does a similar command exist for files, that will create a file and parent directories as needed?

  • Not that I am aware of.. but you could just do mkdir -p /path/to/make && touch /path/to/file... Which would make an empty file in that new directory structure you created all as needed.
    – Kansha
    Jan 30 '13 at 9:10
  • 2
    @Kansha combine that with dirname and basename and we'll only need the single argument; profit! :)
    – akaIDIOT
    Jan 30 '13 at 9:12
  • Aye, good call.
    – Kansha
    Jan 30 '13 at 9:14

Install will do this, if given the source file /dev/null. The -D argument says to create all the parent directories:

anthony@Zia:~$ install -D /dev/null /tmp/a/b/c
anthony@Zia:~$ ls -l /tmp/a/b/c 
-rwxr-xr-x 1 anthony anthony 0 Jan 30 10:31 /tmp/a/b/c

Not sure if that's a bug or not—its behavior with device files isn't mentioned in the manpage. You could also just give it a blank file (newly created with mktemp, for example) as the source.


No, it does not as far as I know. But you can always use mkdir -p and touch after each other:

mkdir -p -- "${f%/*}" && touch -- "$f"

I frequently ran into this kind of situation, so I simply wrote a function in my .bashrc file. It looks like this

function create() {
    num_of_dirs=$(grep -o "/" <<< $arg | wc -l)
    make_dirs=$(echo $arg | cut -d / -f1-$num_of_dirs)
    mkdir -p $make_dirs && touch $arg

So, when I want to create a file inside a path of non-existent directories, I will say

create what/is/it  # will create dirs 'what' and 'is', with file 'it' inside 'is'
  • 1
    My man! - thank you, I called it touchp, like mkdir -p
    – ecoologic
    Jun 7 '19 at 4:53
mkdir -p parent/child && touch "$_/file.txt"

$_ is a shell parameter, it expands to last argument of previous command. Example mkdir test && cd "$_" will create and cd into the directory test.


It's possible to "fake it".

First, some required theory:

Rob Griffiths posted an article in 2007 entitled Easily Create Lots of New Folders on Macworld.com wherein he discussed using the xargs command to read in a list of files to create directories using mkdir.

xargs is capable of referencing a placeholder ({}) with the -I flag, which contains the value for each argument passed to xargs. Here's the difference between with that flag, and without:

$ foo.txt bar.txt | xargs echo
$ => foo.txt bar.txt
$ foo.txt bar.txt | xargs -I {} echo {}
$ => foo.txt
$ => bar.txt

xargs is also capable of running arbitrary shell commands with the sh -c flag:

foo.txt bar.txt | xargs sh -c 'echo arbitrary command!'

Combining the Concepts:

We can combine these concepts with mkdir -p instead of mkdir and the concept in @ldx's answer to produce this:

$ cat files.txt | xargs -I {} sh -c 'f="{}" && mkdir -p -- "${f%/*}" && touch -- "$f"'

This command basically maps each filename in a line-separated list of files, chops off the file part, creates the directories with mkdir -p and then touches the filename in it's respective directory.

Here's a breakdown of what happens in the above command:

Say for instance my files.txt looks like this:

  • cat files.txt produces deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt
  • deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt is piped to xargs
  • because we used -I {}, xargs will translate each argument to it's own command, so we now have:
    • deeply/nested/foo/bar.txt
    • deeply/nested/baz/fiz.txt
  • we then run a shell command that uses the && combinator to group 3 commands that run sequentially - the first command stores the file in an environment variable (that gets re-used on the next file pass) using the placeholder we registered before, so we now have:
    • f=deeply/nested/foo/bar.txt
    • f=deeply/nested/baz/fiz.txt
  • we now have a variable we can pass to mkdir -p, but we need to cut out the filename. Simple enough using '${f%/*}':
    • mkdir -p deeply/nested/foo/
    • mkdir -p deeply/nested/baz/
  • and then we just re-reference the f variable in its entirety when we touch:
    • touch deeply/nested/foo/bar.txt
    • touch deeply/nested/baz/fiz.txt
  • 2
    You have all this explaination for what is essentially cat files.txt | xargs -I {} sh -c 'f="{}" && mkdir -p -- "${f%/*}" && touch -- "$f"', which has UUOC, then you subshell into xargs which subshells back into the shell, when a while read loop makes more sense Mar 10 '16 at 20:53
  • 1
    I'll admit I'm not the most clued up on *nix commands - I don't even know what UUOC is - but I fail to see how this is an awful answer. It is researched, tested and is a working solution to your original question. It's constructive (unlike your rather rude comment). Please, if you feel that I've done something irresponsible here that I should not have, then elaborate further - explain why. I don't care much for opinionated debate that has no substance.
    – razorbeard
    Mar 10 '16 at 21:03
  • 1
    My last comment explains it perfectly. Your entire answer could be better written as while read f; do mkdir -p "$(dirname "$f")"; touch "$f"; done < files.txt. The fact that you cant do a 10 second internet search for UUOC is also telling Mar 10 '16 at 22:04

I was going to suggest as it keeps it on one line, though setting the variable separately allows you to change it and rerun the command from the history pretty easily.

B="./make/this/path" && mkdir -p -- "$B" && touch -- "$B/file.txt"
dir=$(dirname "$f")
test -d $dir || mkdir -p "$dir"
  • 3
    The test isn't needed; mkdir -p doesn't do anything if the dir already exists. Doesn't even return an error.
    – derobert
    Jan 30 '13 at 15:36
  • 1
    And of course, this only creates the directory.
    – user
    Jan 30 '13 at 15:40

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.