How can I have mkdir cd into the newly-created directory?

6,229

Solution 1

Using last argument of command

You don't have to retype the name of the directory created. Use $_ variable:

From bash 4.3 manual:

   _      At shell startup, set to the absolute pathname  used
          to  invoke  the shell or shell script being executed
          as passed in the environment or argument list.  Sub‐
          sequently,  expands to the last argument to the pre‐
          vious command, after expansion.  

So usage would be as so:

bash-4.3$ mkdir mydir
bash-4.3$ cd $_

Using the '{list;}' compound command

If we wanted use just one line, combine the commands into compound command { (note that leading space before { and semicolons for each command are required):

bash-4.3$ pwd
/home/xieerqi
bash-4.3$ { mkdir mydir;cd $_;}
bash-4.3$ pwd
/home/xieerqi/mydir

It's important to note that this {list;} compound command structure is chosen for a reason, because all commands within the list are executed in current shell environment.

And if we want to avoid typing everything over and over, we can make an alias out of it.

bash-4.3$ alias mkcd='{ IFS= read -r d && mkdir "$d" && cd "$d"; } <<<' 
bash-4.3$ pwd
/home/xieerqi
bash-4.3$ mkcd "mydir"
bash-4.3$ pwd
/home/xieerqi/mydir

Here I used "$d" variable for both , but I could have just as equally used "$_":

bash-4.3$ alias mkcd='{ IFS= read -r d && mkdir "$d" && cd "$_"; } <<<'

Solution 2

I suggest creating a function:

function mydir(){ mkdir -p "$1" && cd "$1"; }

it does what you want, you can add it to your .bashrc so it will be available in all your shells.

  • $1 is the first argument you send to the function, the name of directory.

You can use it like:

$ mydir ~/my-new-directory
$ pwd
~/my-new-directory

Note: you can change mydir with mkdir to override it, however I suggest a custom name which does not exist in system like mydir or cmkdir; You can check to see if a command exists using type command.

Solution 3

I usually follow mkdir something by cdAlt + . which completes the command with the last argument of the previous command, i.e. the directory name.

Solution 4

Function

You can make a small function, which you can store in the file ~/.bashrc. Edit the file to add the following lines,

md () {
 mkdir "$1" && cd "$1"
}

Run

source ~/.bashrc

in order to make the change work in the current terminal [window]. The new function will be there, when you open new terminals.

Using && between the commands makes the cd command run only if the mkdir command was successful.

Example: I can use the function md like this to create a test directory testdir in the current directory (in this case my home directory as seen from the prompt),

sudodus@xenial32 ~ $ md testdir
sudodus@xenial32 ~/testdir $ 

Bash shellscript did not work as I expected

I will also describe my difficulties using a small bash shellscript for this purpose, because other people might try it and get confused.

You can store a shellscript in the directory ~/bin. After creating ~/bin and rebooting, it will be in PATH.

Use a name that is not used by any standard command (for example mdscript),

#!/bin/bash

mkdir "$1" && cd "$1"

Make the script executable

chmod ugo+x ~/bin/mdscript

This does not work as intended with

mdscript testdir

because the current directory is only changed in the sub-process of the shell-script, but not in the terminal [window] after finishing the shellscript.

It works when 'sourced', run with the command line

source mdscript testdir

but this is not convenient, not a good answer to the original question.

You can see how it works, if you add a pwd command into the shellscript

#!/bin/bash

mkdir "$1" && cd "$1"
pwd

and run the script mdscript

sudodus@xenial32 ~ $ mdscript testdir
/home/sudodus/testdir
sudodus@xenial32 ~ $ 
Share:
6,229

Related videos on Youtube

Admin
Author by

Admin

Updated on September 18, 2022

Comments

  • Admin
    Admin almost 2 years

    Frequently, I type these commands in bash:

    mkdir something
    cd something
    

    I almost never do this:

    mkdir something
    ls # something in the current directory, not ./something/
    

    And never this:

    mkdir something something2
    

    How can I have mkdir cd into the newly-created directory? By that I mean if I mkdir something, than the command cd something is executed immediately after.

    Example:

    $ pwd
    /home/me
    $ mkdir something
    $ pwd
    /home/me/something
    
  • choroba
    choroba about 7 years
    Double quote the $1 so the function works for directories containing whitespace.
  • choroba
    choroba about 7 years
    Have you tried it? You should quote both, the argument and the variable.
  • Ravexina
    Ravexina about 7 years
    @choroba my mistake +1, I wrote it with quoting in my system that was the reason it was working okay, updated the answer ;) thanks.
  • Sergiy Kolodyazhnyy
    Sergiy Kolodyazhnyy about 7 years
    I have to use Esc instead of Alt. For some reason that works instead for me in both xterm and Terminator.
  • gardenhead
    gardenhead about 7 years
    Should replace ; with && to handle the case where mkdir fails (as it wasn't invoked with -p)
  • G-Man Says 'Reinstate Monica'
    G-Man Says 'Reinstate Monica' about 7 years
    You got that to work as a script?  Really?
  • G-Man Says 'Reinstate Monica'
    G-Man Says 'Reinstate Monica' about 7 years
    (1) You should probably mention the fact that the ; between the last command and the } is required. This is a frequent source of confusion for people who are accustomed to ( cmd1 ; cmd2 ) grouping, where a ; is not required after the last command. (2) At the risk of splitting hairs, if you have a ; before the }, you don’t need a space. Also, of course, spaces before semicolons are not required, either. … (Cont’d)
  • G-Man Says 'Reinstate Monica'
    G-Man Says 'Reinstate Monica' about 7 years
    (Cont’d) …  (3) That’s a really clever trick, ending an alias with <<< to capture the argument into a variable, which you can then use multiple times.   I don’t recall ever seeing that before, but I’ll be adding it to my toolbox (although it is painfully inflexible).   … (Cont’d)
  • G-Man Says 'Reinstate Monica'
    G-Man Says 'Reinstate Monica' about 7 years
    (Cont’d) …  (4) Using unnecessary external programs in aliases is inelegant.  Here, the use of xargs is harmful. (4a) It strips leading and trailing whitespace from the argument. (4b) It turns interior whitespace into a single space (even if it is multiple spaces, or a tab). (4c) It strips out matching pairs of quotes, and goes crazy if you give it non-matching quotes.  Why not just do '{ IFS= read -r arg  && cmd1 "$arg"  && cmd2 "$arg" ; } <<<'?  (5) What do you mean when you say “I could have just as equally used "$_"”.in the context of an alias using <<<?
  • sudodus
    sudodus about 7 years
    @G-Man, You are right, it works as a function but it does not work as a script. The current directory is only changed inside the script's sub-process, but after finishing the script, the terminal [window] is still in its original current directory. It works, when 'sourced' as source md testdir but that is not a convenient way to run it. - I will modify my answer.
  • Sergiy Kolodyazhnyy
    Sergiy Kolodyazhnyy about 7 years
    @G-Man Very valid comments 1 and 4. I wasn't aware that xargs has these issues. I've edited my answer. As for comment 5, we could use cd "$_" instead of using "$d" everywhere. Just a small point to link it with previous section of the answer, not really important.