Make a directory and change to it A basic shell function to create a directory and change to it goes like this:

mkcd () { mkdir "$1" &amp;&amp; cd "$1"; }


This works well in many cases but breaks in unusual cases (e.g. if the argument begins with -).

I'm writing a more sophisticated version. This version calls mkdir -p to create parent directories if needed and just change to the directory if it already exists. It has these design goals:


Work in any POSIX compliant shell.
Cope with any file name.
If the shell has logical directory tracking, where foo/.. is the current directory even if foo is a symbolic link to a directory, then the function must follow that logical tracking: it must act as if the cd builtin was called and magically created the target directory.
If a directory is created, it is guaranteed that the function changes into it, as long as there is no race condition (another process moving a parent directory, changing relevant permissions, …).


Here is my best current effort. Does it meet the goals above? Are there situations where the behavior is surprising?

mkcd () {
  case "$1" in
    */..|*/../) cd -- "$1";; # that doesn't make any sense unless the directory already exists
    /*/../*) (cd "${1%/../*}/.." &amp;&amp; mkdir -p "./${1##*/../}") &amp;&amp; cd -- "$1";;
    /*) mkdir -p "$1" &amp;&amp; cd "$1";;
    */../*) (cd "./${1%/../*}/.." &amp;&amp; mkdir -p "./${1##*/../}") &amp;&amp; cd "./$1";;
    ../*) (cd .. &amp;&amp; mkdir -p "${1#.}") &amp;&amp; cd "$1";;
    *) mkdir -p "./$1" &amp;&amp; cd "./$1";;
  esac
}
Some error messages may be confusing like:

$ mkcd /foo/../bar
mkcd:cd:3: no such file or directory: /foo/..
$ mkcd /bin/../bar
mkdir: cannot create directory `./bar': Permission denied


Probably not much you can do about that.