Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I find myself repeating a lot of:

mkdir longtitleproject
cd longtitleproject

Is there a way of doing it in one line without repeating the directory name? I'm on bash here.

share|improve this question
mcd from… – Mikel Mar 12 '11 at 1:32
Related (but more general): Run two commands on one argument (without scripting). – G-Man Aug 20 at 9:19

6 Answers 6

up vote 72 down vote accepted

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 - but isn't just -, then mkdir and cd will interpret it as an option. If it's just -, then cd will interpret it to mean $OLDPWD. If it's + followed by 0 or more digits, then cd in zsh will interpret it as an index in the directory stack. You can fix the first problem, but not the other two, by passing -- before the argument. You can fix all of these 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";;

(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.
share|improve this answer
Thanks! the Esc . seems the most convenient to me, does the key sequence have any special meaning? – Duopixel Mar 12 '11 at 1:36
It's just the Bash (and inherited from ksh, and also works in zsh) sequence for "repeat last word of previous command". I use it quite often. – geekosaur Mar 12 '11 at 1:46
@Gilles I'm beginning to think that the "Gilles" account is actually shared by a panel of experts. ;-) – Keith Mar 12 '11 at 3:24
@StephaneChazelas /a/b/..// would actually work but not /a/b/../c. Fixed. I've put the question to a broader audience. – Gilles Jan 30 '13 at 22:26
mkcd() { mkdir -p "$1" && cd "$1"; } doesn't seem to be a problem in (my instance of) zsh. mkdir -p /var/tmp/somewhere/else /tmp/here; cd /tmp/here; ln -s /var/tmp/somewhere/else mylink; mkdir -p mylink/../foo && cd mylink/../foo; pwd (includes the setup and) displays /tmp/here/foo which is what was created (and what I expected). bash erroneously creates and changes to /var/tmp/somewhere/foo. – Adam Katz Jan 15 at 18:39

It would never have occurred to me to script up this behaviour because I enter the following on a near daily basis ...

$ mkdir someDirectory<ENTER>
$ cd !$

where bash kindly substitutes !$ with the last word of the last line; i.e. the long directory name that you entered.

In addition, filename completion is your friend in such situations. If your new directory was the only file in the folder a quick double TAB would give you the new directory without re-entering it.

Although it's cool that bash allows you to script up such common tasks as the other answers suggest I think it is better to learn the command line editing features that bash has to offer so that when you are working on another machine you are not missing the syntactic sugar that your custom scripts provide.

share|improve this answer
Is there a good place to find out about most important bash quirks like this one? – dominicbri7 Oct 7 at 2:48
@dominicbri7 Generally comes under "bash command line editing" Googling same gives the following as a top result More specifically, !$ is an example of a Word Designator see – Rob Oct 7 at 14:19

As per What customizations have you done on your shell profile to increase productivity?, this is how I do it:

# make a directory and cd to it
    test -d "$1" || mkdir "$1" && cd "$1"

it means it also works if the directory already exists.

share|improve this answer
The -p option to mkdir will suppress errors. – glenn jackman Mar 12 '11 at 5:42
@glenn jackman: Indeed it does, thanks. – Mikel Mar 12 '11 at 6:29
+1 to use test -d and || – Johan Mar 12 '11 at 21:06
mcd is an already existing command. Though you've just given an example, I used it myself as it's a letter shorter than mkcd. – Dharmit Apr 13 '11 at 14:44
mtools provides the mcd command. Its man page says "The mcd command is used to change the mtools working directory on the MS-DOS disk." – Dharmit Apr 14 '11 at 6:11

This is the one-liner that you need. No other config needed:

mkdir longtitleproject && cd $_

The $_ variable, in bash, is the last argument given to the previous command. In this case, the name of the directory you just created. As explained in man bash:

_         At  shell  startup,  set to the absolute pathname used to invoke
          the shell or shell script being executed as passed in the  envi‐
          ronment  or  argument  list.   Subsequently, expands to the last
          argument to the previous command, after expansion.  Also set  to
          the  full  pathname  used  to  invoke  each command executed and
          placed in the environment exported to that command.  When check‐
          ing  mail,  this  parameter holds the name of the mail file cur‐
          rently being checked."$_" is the last argument of the previous command.
share|improve this answer

Or you could just create a short variable on-the-fly and use it twice x = longproject ; mkdir $x ; cd $x - which I admit is still longer than using a shellscript function :)

share|improve this answer

If you use Oh My Zsh, there's a command called take that does exactly this. It would look something like this.

take myfolder

I actually found this one by accident. I just looked and it's listed on this cheatsheat from the Oh My Zsh GitHub wiki. It's quite a useful command, and apparently very easy to create yourself.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.