Create file and its parent directory

All we need is an easy explanation of the problem, so here it is.

I know that touch command creates a file:

touch test1.txt

but how I can create a file and its full path?

for example my desktop contains nothing:

~/Desktop/$ ls
~/Desktop/$

and I want to create 1.txt in ~/Desktop/a/b/c/d/e/f/g/h/1.txt.
Can I do this with a simple command like:

$ touch ~/Desktop/a/b/c/d/e/f/g/h/1.txt

instead of create full path manually and then create the file?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

touch is not able to create directories, you need mkdir for that.

However, mkdir has the useful -p/--parents option which creates a full directory structure.

From man mkdir:

   -p, --parents
          no error if existing, make parent directories as needed

So the command you need in your specific situation is:

mkdir -p ~/Desktop/a/b/c/d/e/f/g/h/ && touch ~/Desktop/a/b/c/d/e/f/g/h/1.txt

If you think you will need this more often and don’t want to type the path twice every time, you can also make a Bash function or a script for it.

  • Bash function (append this line to ~/.bashrc to persitently have it available to your user, otherwise it will vanish again when you exit your terminal):

    touch2() { mkdir -p "$(dirname "$1")" && touch "$1" ; }
    

    It can be simply used like this:

    touch2 ~/Desktop/a/b/c/d/e/f/g/h/1.txt
    
  • Bash script (store it in /usr/local/bin/touch2 using sudo to make it available for all users, else in ~/bin/touch2 for your user only):

    #!/bin/bash
    mkdir -p "$(dirname "$1")" &&
        touch "$1"
    

    Don’t forget to make the script executable using chmod +x /PATH/TO/touch2.

    After that you can also run it like this:

    touch2 ~/Desktop/a/b/c/d/e/f/g/h/1.txt
    

Method 2

One can use install command with -D flag.

bash-4.3$ install -D /dev/null mydir/one/two

bash-4.3$ tree mydir
mydir
└── one
    └── two

1 directory, 1 file
bash-4.3$ 

If we have multiple files, we might want to consider using a list of items(note, remember to quote items with spaces), and iterating over them:

bash-4.3$ for i in mydir/{'subdir one'/{file1,file2},'subdir 2'/{file3,file4}} ; do 
> install -D /dev/null "$i"
> done
bash-4.3$ tree mydir
mydir
├── one
│   └── two
├── subdir 2
│   ├── file3
│   └── file4
└── subdir one
    ├── file1
    └── file2

Or alternatively with array:

bash-4.3$ arr=( mydir/{'subdir one'/{file1,file2},'subdir 2'/{file3,file4}} )
bash-4.3$ for i in "${arr[@]}"; do  install -D /dev/null "$i"; done
bash-4.3$ tree mydir
mydir
├── one
│   └── two
├── subdir 2
│   ├── file3
│   └── file4
└── subdir one
    ├── file1
    └── file2

Method 3

mkdir -p parent/child && touch $_/file.txt

Method 4

For this purpose you can create your own function, example below:

$ echo 'mkfile() { mkdir -p "$(dirname "$1")" && touch "$1" ;  }' >> ~/.bashrc
$ source ~/.bashrc
$ mkfile ./fldr1/fldr2/file.txt

First we insert a function to the end of ~/.bashrc file using echo command. The -p flag in function allows to create the nested folders, such as fldr2 from our example. Finally we update the file with source command and eventually execute recently created mkfile command

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply