The simplest way is to use a shell function:
mkcd() {
mkdir -p -- "$1" && cd -- "$1"
}
Place it in your .bashrc
file to make it be available to you just like another shell command.
The reason why it doesn't work as an external script is cd
changes the current directory of the running script but doesn't affect the calling one. This is by design! Each process has its own working directory which is inherited by its children, but the opposite is not possible.
Unless part of a pipeline, run in the background or explicitly in a subshell, a shell function doesn't run in a separate process but in the same one, just like if the command has been sourced. The current directory shell can then be changed by a function.
The &&
used here to separate both commands used means, if the first command succeeds (mkdir
), run the second one (cd
). Consequently, if mkdir
fails to create the requested directory, there is no point trying to go into it. An error message is printed by mkdir
and that's it.
The -p
option used with mkdir
is there to tell this utility to create any missing directory that is part of the full path of the directory name passed as argument. One side effect is that if you ask to create an already existing directory, the mkcd
function won't fail and you'll end up in that directory. That might be considered an issue or a feature. In the former case, the function can be modified for example that way which simply warns the user:
mkcd() {
if [ -d "$1" ]; then
printf "mkcd: warning, \"%s\" already exists\n" "$1"
else
mkdir -p "$1"
fi && cd "$1"
}
Without the -p
option, the behavior of the initial function would have been very different.
If the directory containing the directory to create doesn't already exists, mkdir
fails an so does the function.
If the directory to be create already exists, mkdir
fails too and cd
isn't called.
Finally, note that setting/exporting PWD
is pointless, as the shell already does it internally.
Edit: I added the --
option to both commands for the function to allow a directory name starting with a dash.
cd
, you picked a special case right from the start. :Dcd
-related info (return to the previous directory usingcd -
, usepushd
andpopd
to maintain a "stack" of directories): superuser.com/questions/324512/…mkdir -p /very/long/path
, then usecd
, space, and then press Alt+.
to repeat the last argument, i.e. the dir name.mkdir -p /very/long/path; cd !#:2
. The string!#:2
will expand to argument nr. 2 (that is, the third argument,/very/long/path
, as counting starts with zero).!$
. I use this particular trick all the time, though there is a lot more you can do with history expansion.