1. Overview

As a sysadmin, we often have to create nested directories with an empty file for the application that manages it. Usually, we get the “No file or directory” error when we’re copying the file to a destination that doesn’t exist.

Obviously, creating multiple nested directories in the terminal is a tedious and time-consuming task that calls upon the need to create the destination directory and file in a simple manner.

This tutorial will expound on different ways of creating a directory path and file in single command in Linux systems. Now, let’s get into the nitty-gritty of it.

2. Using mkdir and touch Commands

With the combination of both mkdir and touch commands, we can accomplish the task of creating a directory and a file in a single go. Here, the parent option of mkdir helps us to create the parent directory (unless it exists) without any error, while the touch command creates a file. Generally, the touch command doesn’t put anything into the file.

Let’s delve into an example for better comprehension.

2.1. CLI Mode Execution

Firstly, we get the whole path structure and file name in the bash variable FILE. Let’s view the content inside the FILE using the echo command by prepending the $ symbol to it:

$ FILE=./dir1/dir2/dir3/sample.txt
$ echo $FILE
./dir1/dir2/dir3/sample.txt

Secondly, dirname assists us to get the full directory structure by removing the filename. As a result, it prints the whole directory structure that has to be created by mkdir:

$ dirname $FILE
./dir1/dir2/dir3

Thirdly, let’s create the directories using the -p option to make nested directories. Lastly, the touch command creates the empty file in the new path. We use a double ampersand to stretch the two commands.

The double ampersand is preferred over semicolon as the latter executes both the commands simultaneously, while the former executes the second command only after the successful execution of the first command.

Here’s how the mkdir and touch commands help to create the file with the specified directory structure:

$ cd dir1
-bash: cd: dir1: No such file or directory

$ ls -ltrh "$FILE"
ls: cannot access './dir1/dir2/dir3/sample.txt': No such file or directory

$ mkdir -p "$(dirname $FILE)" && touch "$FILE"

The tree command in Linux helps us to understand the directory hierarchy in a tree-like format:

$ tree dir1/
dir1/
└── dir2
    └── dir3
        └── sample.txt

2 directories, 1 file

2.2. Writing a Custom Bash Script

Likewise, if we want to create multiple paths with subsequent files, it is wise to create a custom bash script for these repetitive tasks.

Next, consider the below bash function create_folder_file — which is essentially a set of commands that repeats. The main intention of the function is to make our bash scripts more readable and to prevent code repetition.

It’s pretty common in a Linux environment to include shebang in the first line of a script as it helps the program loader to execute the correct interpreter.

The path and file information is given by the user as an input argument through the command prompt. The arguments are further iterated by a special parameter $@ that expands the positional parameters, starting from one. Here, the dirname executes at subshell environment as it is given within the parenthesis.

However, the code block throws an alert if we miss providing the path and file information:

$ cat create_folder_file.sh
#!/bin/bash
create_folder_file() {
    for file_path_info in "$@"; do
        mkdir -p -- "$(dirname -- "$file_path_info")"
        touch -- "$file_path_info"
    done
}
if [ $# -lt 1 ]; then
    echo "Error: Argument missing, please enter the filename with fullpath.";
    exit 0;
fi

Let’s provide the executable permissions to the script and see what happens when we try to execute the create_folder_file.sh script:

$ ls -ltrh create_folder_file.sh
-rw-rw-r-- 1 tools tools 297 Sep 10 19:41 create_folder_file.sh
$ chmod 755 create_folder_file.sh
$ ls -ltrh create_folder_file.sh
-rwxr-xr-x 1 tools tools 297 Sep 10 19:41 create_folder_file.sh
$
$ tree full fullnew
full [error opening dir]
fullnew [error opening dir]

0 directories, 0 files

Now, let’s execute the script by providing multiple folder paths and file information:

$ ./create_folder_file.sh full/path/folder/file.txt fullnew/path/folder/file.txt
$
$ tree full fullnew
full
└── path
    └── folder
        └── file.txt
fullnew
└── path
    └── folder
        └── file.txt

4 directories, 2 files

Furthermore, let’s create an alias to provide a command-like execution view. Here, we’re creating a temporary alias for a quick illustration. However, permanent aliases can also be created in the .bashrc_aliases file.

After creating the alias, we can just type make and press TAB for auto-complete as illustrated below:

$ alias make_dir_file="./create_folder_file.sh"
$
$ make_dir_file 11/22/33/44.txt 44/55/66.txt 111/222/333/444.txt 444/555/666.txt
$ tree 11 44 111 444
11
└── 22
    └── 33
        └── 44.txt
44
└── 55
    └── 66.txt
111
└── 222
    └── 333
        └── 444.txt
444
└── 555
    └── 666.txt

6 directories, 4 files

3. Using the install Command

At times, a genuinely useful command draws lesser attention than it actually deserves. Perhaps this was the case of the Linux install command. It’s less acknowledged, even though it has awesome built-in features that even help us to set the permissions, groups, owner, and so on.

For the sake of illustration, let’s take the two variables SRC_FILE and DEST_FILE with full path and file name:

$ SRC_FILE=./source/file/path/sample.txt
$ DEST_FILE=./destination/file/path/destination-sample.txt
$
$ tree source destination
source
└── file
    └── path
        └── sample.txt
destination [error opening dir] 
2 directories, 1 file 

Now, let’s execute the install command by providing the source and destination information as illustrated below. The -D option of the command helps to create the leading components of the destination and then it copies the file from source to destination:

$ install -D "$SRC_FILE" "$DEST_FILE"
$
$ tree ./destination
./destination
└── file
    └── path
        └── destination-sample.txt

2 directories, 1 file

4. Using cp Command

Traditionally, we’ve been using the Linux cp (copy) command to create a destination file from the available source. It has the option to preserve the directory structure and permissions:

$ mkdir dir4 && cp --parents dir1/dir2/dir3/sample.txt dir4
$ tree dir4
dir4
└── dir1
    └── dir2
        └── dir3
            └── sample.txt

3 directories, 1 file

5. Conclusion

In short, we explored the different ways of scheduling tasks using mkdir and touch, install, and cp commands. Along the way, we also learned the usage of bash script for mkdir and touch to create multiple directories and files in a single go.

Similarly, we can also wrap a bash function alongside install and cp commands to manage the repetitive folder/file creation. On the whole, depending on our use-case, we may choose any one of these to achieve seamless creation of directories and files.