There's no built-in command, but you can easily write a function that calls mkdir then cd:
mkcd () {
mkdir "$1"
cd "$1"
}
Put this code in your ~/.bashrc file (or ~/.kshrc for ksh users, or ~/.zshrc for zsh users). It defines a function called mkcd. "$1" will be replaced by the argument of the function when you run it.
This simple version has several defects:
- You cannot create a chain of subdirectories at once. Fix: pass the
-p option to mkdir. (This may or may not be desirable, as it increases the risk of a typo going undetected, e.g. mkcd mydierctory/newsub will happily create mydierctory and mydierctory/newsub when you meant to create newsub inside the existing mydirectory.)
- If the argument begins with
-, then mkdir and cd will interpret it as an option. If the argument is + followed by 0 or more digits, then cd will interpret it as an index in the directory stack. You can fix the former problem, but not the latter, by passing -- before the argument. You can fix both problems by prepending ./ to the argument if it's a relative path.
mkdir doesn't follow CDPATH, but cd does, so if you've set CDPATH to a value that doesn't begin with . (an admittedly somewhat unusual configuration), then cd may bring you to a different directory than the one that was just created. Prepending ./ to relative paths fixes this (it causes CDPATH to be ignored).
- If
mkdir fails, it tries to execute cd. Fix: use && to separate the two commands.
Still fairly simple:
mkcd () {
case "$1" in /*) :;; *) set -- "./$1";; esac
mkdir -p "$1" && cd "$1"
}
This version still has the potential to make cd go into a different directory from the one that mkdir just created in one edge case: if the argument to mkcd contains .. and goes through a symbolic link. For example, if the current directory is /tmp/here and mylink is a symbolic link to /somewhere/else, then mkdir mylink/../foo creates /somewhere/else/foo whereas cd mylink/../foo changes into foo. It's not enough to look for symbolic links in the argument, because the shell also tracks symbolic links in its own current directory, so cd /tmp/mylink; mkdir ../foo; cd ../foo does not change into the new directory (/somewhere/else/foo) but into /tmp/foo. A fix for this is to let the cd builtin resolve all .. path components first (it doesn't make sense to use foo/.. if foo doesn't exist, so mkdir never needs to see any ..).
We come to this robust if slightly gory version:
mkcd () {
case "$1" in
*/..|*/../) cd -- "$1";; # that doesn't make any sense unless the directory already exists
/*/../*) (cd "${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd -- "$1";;
/*) mkdir -p "$1" && cd "$1";;
*/../*) (cd "./${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd "./$1";;
../*) (cd .. && mkdir -p "${1#.}") && cd "$1";;
*) mkdir -p "./$1" && cd "./$1";;
esac
}
(Exercise: why am I using a subshell for the first cd call?)
If mkdir fails, I want to be sure not to change the current directory. Changing back with cd - or $OLDPWD isn't good enough if the shell doesn't have permission to change into its current directory. Also, calling cd updates OLDPWD, so we only want to do it once (or restore OLDPWD).
There are also less specialized ways to not have to retype the word from the previous line:
- Type
cd , then Esc . (or Alt+.) to insert the last argument from the previous command.
cd !$ executes cd on the last argument of the previous command.
- Press Up to recall the previous command line, then edit it to change
mkdir into cd.
mcdfrom unix.stackexchange.com/questions/6628/… – Mikel Mar 12 '11 at 1:32