In a bash script, how can I go to a directory whose name is stored in a variable?

12,391

The cd command changes what directory you are in. Run help cd for details.

If dirName is a shell variable that contains the name of the directory you want to go to, then

cd -- "$dirName"

will go there. For example, if you start out in /home/my_user_name/SCRIPTS and the variable dirName contains the text foo, then that command brings you to /home/my_user_name/SCRIPTS/foo.

If you always want dirName to be interpreted as a relative path in /home/my_user_name/SCRIPTS, regardless of where the user runs your script from, then use:

cd -- "/home/my_user_name/SCRIPTS/$dirName"

You may have noticed the leading -- argument and the use of quotation:

  • In a script, when passing user input as arguments to a command that accepts options starting with - or --, it's usually a good idea to pass the -- option first. Most commands that accept filename arguments support this syntax (you should always check, though). It means that all subsequent arguments are to be interpreted as filenames rather than as options.

    To understand this, try running ls -l, and try running ls -- -l. You don't usually need to use the -- argument when you're typing commands manually. But in a script that passes the value of unsanitized input to a command, it's frequently used.

  • In both commands, I have used double quotes (" "). This is usually what you want when expanding a variable that contains a filename.

    Like if you used no quotes at all, but unlike single quotes (' '), double quotes permit parameter expansion. So they don't prevent $dirName from being expanded to the value that was assigned to it by the read command. However, unlike not using quotes at all, but like single quotes, double quotes prevent word splitting. That way, if the variable contains whitespace characters (or characters present in IFS, if that has been set), it will still work properly.

    See also 3.1.2 Quoting in the Bash Reference Manual.

I recommend also using double-quotes in your mkdir commmand, and probably also --:

mkdir -- "$dirName"

Note, however, that changing the current directory in a shell script does not cause the calling process's current directory to be changed. This is by design (and holds in most, if not all, operating systems, including Windows). When a program runs another program, it does not expect its own current directory to be changed.

Every program has its own environment, and its own current directory. When you start a new program, it inherits this from the program that started it, but it has its own copy. When a child process changes its current directory, that is not reflected in the parent process.

Often, when you want to change directory for the caller, the correct approach is to reconsider your design. Do you really need this?

Essentially the only situation where it is reasonable to change directory for the caller is when your script is really just a list of commands that would be just as well be run directly by the caller. When that is the case, you can source the script instead of running it. For example, suppose you are currently running your script with the command:

./my_script

Then you can instead source it with:

. ./my_script

This alternative syntax is also supported:

source ./my_script

The Bash shell supports both the . and source builtins, and they are equivalent. (Run help . or help source for details.)

This causes all the commands in your script to be run in the current shell, rather than in a new shell (which is what happens when you actually run a shell script).

Share:
12,391

Related videos on Youtube

andrej benedičič
Author by

andrej benedičič

Updated on September 18, 2022

Comments

  • andrej benedičič
    andrej benedičič over 1 year

    I'm doing a FileCreator script:

    #!/bin/bash
    
    echo "Welcome to the file creator! Please type the directory name:"
    read dirName
    
    mkdir $dirName
    
    #Now I want to change directory to that new $dirName that will be run from Terminal.
    

    My question is now, how to change the path to this new directory dirName that is visible on Terminal. So, at the end, path should be: /home/my_user_name/SCRIPTS/dirName when I run this script ...

    Please, just a suggestion? :)

    • AlexP
      AlexP over 7 years
      cd $dirName, surely?
    • andrej benedičič
      andrej benedičič over 7 years
      Yes, but if I add this cd $dirName and run from Terminal this script, it isn't at this directory ... I tried.
    • Eliah Kagan
      Eliah Kagan over 7 years
      @andrejbenedičič Ah, I see. You want the calling shell to be in that directory, even after the script is finished running. I'll expand my answer.
    • Rmano
      Rmano over 7 years
      Because when you exit the script, the directory will change back to where it was before. It's a feature....
    • andrej benedičič
      andrej benedičič over 7 years
      Aha. So if I want to go to that directory after running the script, I still need to run cd /name_of_the_wanted_directory later on Terminal? So it won't be automatically located at new directory?
  • andrej benedičič
    andrej benedičič over 7 years
    woooooow, thank you for the nice explanation. So, then the path it won't be automatically in dirName after executing this script? :D
  • Eliah Kagan
    Eliah Kagan over 7 years
    @andrejbenedičič Yes, when you run a script (./my_script) rather than sourcing it (. ./my_script), the parent shell does not have any of its own variables changed. However, cd in shell scripts is still frequently useful (and is even often useful because one can change directory in the script without affecting the caller). For example, if you plan to expand your script with code that creates a file in the directory you've cd'd to (I'm just guessing, based on the way you described what you were trying to do), then that should work fine.
  • andrej benedičič
    andrej benedičič about 7 years
    I run this script as . WorkingWithFiles.sh and it works. Thank you, @EliahKagan.