Let mkdir create parents directories

I noticed that it is more than a year since the last post, so I thought that a small new content would have been easier to write. This in particular refers to an extension I wrote some time ago for the mkdir system call to make it a bit more proactive 😄.

90% of the times, I use mkdir to create a new folder in the current directory, so the few times I want to create a new folder in a deeper path I always forget to add the --parent flag.

me/blog $ mkdir foo/bin/bar
mkdir: cannot create directory ‘foo/bin/bar’: No such file or directory

as the Man-pages would tell you, since the parent directory foo/bin does not exist, mkdir fails to create bar, but what if mkdir were so kind to tell me just that, and suggests to add the flag on my behalf? 😄

This is actually somehow easy.

First of all, you need a way to define new functions in your shell. I use zsh, but in bash would be the same: write a function definition in a file and source it in .bashrc or .zshrc.

This comes from my .zshrc

#
# Functions and aliases
#
source ~/.dot/.config/cconf/zsh/functions.zsh

What to do for mkdir?

  1. override it with a custom function ➡️ function mkdir() {}
  2. find the parent directory mkdir expects to exist already ➡️ echo $1 | grep -E -q '[\S+/]+'
  3. if it doesn’t exist, ask if it must be created or not ➡️ echo "Press ENTER to run mkdir with --parents."

Ok, point 2 probably requires some explaination, so let’s back to the example above

me/blog $ mkdir foo/bin/bar

bar is the folder to be created, while foo/bin/ is the parent. The grep expression above looks for any sequence of substrings ending with slash /: foo/, foo/bar/, etc., but not bar, or foo, which would be a directory in the current folder.

So putting all these pieces together:

function mkdir() {
    # extend mkdir with custom features
    # propose adding "--parents" flag.
    echo $1 | grep -E -q '[\S+/]+'
    if [[ $? == 0 && ! -d $1 ]]; then
        # one of the directories in $1 path do not exist
        # suggest adding "--parents" flag.
        echo "# Some parents in $1 do not exist. Press ENTER to run mkdir with --parents."
        read
        command mkdir --parents $@
        echo "# done"
    else
        command mkdir $@
    fi
}

Let’s try again

me/blog $ mkdir foo/bin/bar                                                                                    
# Some parents in foo/bin/bar do not exist. Press ENTER to run mkdir with --parents.

# done

me/blog $ tree | grep -e foo -e bar -e bin
├── foo
│   └── bin
│       └── bar

Of course in a similar manner you can override rm as well (see here).