5 Answers
5

This is an optional feature, that is not always desired - especially in scripts. Consider following drawbacks in case of scripts:

The fact that directory already exists is not reported: If a script is supposed to put some files in a newly created directory and that directory already exists and contains files, the script can make a lot of mess. (It will be toilsome to later filter out the files that were placed there by the script.)

On the flip-side of the above, some script (or part of such) may depend on a directory structure created earlier (possibly by other package/script). For example, a package installation script might need to put libraries in a subdir /usr/local/lib/GreatSoftware/ImportantPartOfIt, but the libraries depend on / link to stuff under /usr/local/lib/GreatSoftware. If this is missing, the script should not continue.

The generic behavior of mkdir makes it easy and natural, as such situations are reported and can be caught straight away.

You can make an alias for it if you want to always use mkdir -p in your shells:

I wouldn't suggest to alias a standard command to make it behaving a non standard way. That would make the scripts non portable and might confuse readers. Creating a new alias or function, like alias mkdp="mkdir -p" would be more advisable.
–
jlliagreOct 31 '11 at 12:56

Indeed but you missed my point. Aliasing a standard command to change its behavior, even for your own use, is not a recommended practice. The worst example being the ubiquitous alias rm='rm -i'.
–
jlliagreOct 31 '11 at 14:10

1

@jlliagre Not recommended by whom? ;) But yes, I agree, I would myself rather use a different alias - but for practical, not ideological reasons. I also don't think rm -i alias is always bad - though might lead to bad habits. Certainly not all command aliases are equally good/bad - consider ls="ls --color=auto" or ssh="TERM=xterm ssh" for example.
–
rozcietrzewiaczOct 31 '11 at 14:16

There is nothing ideological in my recommendation. The rm alias is indirectly responsible of many lost files (I have met plenty of victims of this alias). I was suspecting the mkdir one to have, to a much lesser extent, unwanted side effects. Of course, I'm not against cosmetic, not behavioral, changes like your ssh and ls examples.
–
jlliagreOct 31 '11 at 21:35

Of course one could argue that parent directory creation should be the default and some check option could be used to prevent the directory creation if the parent does not exist.

But the reason why it is the other way around is just history. The basic version of mkdir did not create parent directories. This is why the X11 distributions came along with a command named mkdirhier which was able to fulfil this task: check whether the parent directories exist and create them if neccessary.

Later on this functionality was added to the command mkdir on many UNIX versions (I don't know if it is in the POSIX standard nowadays). To maintain compatibility this feature was made available by turning on an option flag: -p.

Why is it bad to have it turned on by default? Scripts may rely on mkdir failing if the parent directory does not exist. Especially as user root it could be dangerous to create directory trees by default.

Example:

if mkdir /backup/$(uname -n)/$(date +%Y%m%d)
then
perform_backup ...

In this example the directory would be created and the backup performed even is the filesystem /backup is not mounted and the parent /backup/$(uname -n) does not exist if the default would be the other way around.

Rule of thumb: It is good practice not to change the default behaviour of any tool. If desired provide options to allow changing the default behaviour.

In the beginning, there was only the bare mkdir command. In accordance with Unix's design principles, this simple command performed one simple task: creating a directory.

Later, mkdir acquired a -p option to handle a common use case where the caller wants to create zero, one or more directories to ensure that a particular path exists. This was not made the default operation for several reasons. First, not all systems had this more complex feature, and requiring the -p option meant that scripts that used it would get a reasonable error message (something like mkdir: invalid option -z) rather than strangely failing to create directories occasionally. Second, and most importantly, the behavior of mkdir -p is not a compatible replacement of mkdir in all cases.

In particular, on most fileystems, mkdir is an atomic operation. If a program runs mkdir playground and the command succeeds, the program knows that it created the playground directory. This allows the program to treat the new directory as its exclusive playground: if another instance of the same program is running concurrently, its call to mkdir playground will fail. This property is obviously not provided by mkdir -p since it allows the argument to exist.

If mkdir -p had existed from the start, it could have been made the default mode, with something like mkdir -a for the single-directory creation command. But that would not have followed the usual Unix design philosophy: most basic utilities are simple wrappers around the underlying primitives, with fancier behavior (like creating multiple directories in one go) requiring fancy options.

To me, the issue is that the behavior of the -p option if it were the default is essentially a side effect. It adds complexity to a command by doing something additional to what you asked it to do. It's one more invisible thing to have to remember. One of the basic rules of sound programming practice is to avoid side effects.

Modern programming languages are so powerful that it's relatively easy to build whatever complex command you may need from the primitives a language provides. Doing so involves making a conscious decision about what behavior is required and also leaves a concrete, visible record of what has been done.