2

I am trying to write a simple shell script, which will change the directory to the shell script directory and echo it.

This is the script:

#!/bin/bash
# cd '/explicit/path/to/script'
cd $(dirname $0)
echo $(dirname $0)

The output indeed is always, even if I use an explicite cd to the script dir.

/bin

What am I missing?

3
  • How are you running the script? May 24, 2016 at 6:08
  • run it from within home dir: . /path/to/script.sh
    – Skip
    May 24, 2016 at 6:10
  • 2
    you're sourcing the script, not executing it. $0 is probably /bin/bash (i.e. your current command-line shell) from the sourced script's POV.
    – cas
    May 24, 2016 at 6:11

2 Answers 2

4

You need to run the script instead of sourcing it:

/path/to/script.sh

(without .).

When you run

. /path/to/script.sh

$0 is your current shell, which is presumably in /bin (hence the behaviour you're seeing). Note that it needn't be /bin/bash, the shebang doesn't have any effect when sourcing a script.

Lucas' other points are valid, you should use quotes and just run dirname directly, without echo.

1
  • If the OP wants to change to that directory, he may want to call the script with cd "$(/path/to/script)" - however, it must be executed instead of sourced; and an executed script runs in an own subshell and hence cannot change the directory of the calling shell. There are other approaches to do so better (aliases, functions, ...) May 24, 2016 at 11:21
3

The variable $0 points to the shell script that you execute itself. So if you have a file in that contains this

#!/bin/sh
echo "$0"

and copy it to /bin/my-script and to ~/somewhere/my-script-2, make both copies executable you can observe this behavior (I assume /bin is in your $PATH):

$ my-script
/bin/my-script
$ ~/somewhere/my-script-2
/home/luc/somewhere/my-script-2
$ cd
$ somewhere/my-script-2
somewhere/my-script-2
$ ../../bin/my-script
../../bin/my-script
$ cd /bin
$ ./my-script
./my-script

and so on.

In an interactive shell $0 points to the shell you execute and that is most probably in /bin. So if you source the above shell scripts you will always see the path to your shell interpreter: /bin/bash . For this the two script don't have to be executable:

$ . my-script
/bin/bash
$ . ~/somewhere/my-script-2
/bin/bash
$ cd
$ . somewhere/my-script-2
/bin/bash
$ . ../../bin/my-script
/bin/bash
$ cd /bin
$ . ./my-script
/bin/bash

The reason is that a sourced script is executed in the same process that sources it and $0 is not changed ($@ is updated though).

If dirname "$0" prints /bin for you, that just means the file you execute is in /bin or you are running dirname from a interactive session or a sourced script and the interpreter you use is in /bin.

Some other points:

  • You don't need to do echo "$(dirname "$0")", dirname "$0" will do the same.
  • Use pwd the get the current working directory.
  • Put quotes around $0 and command substitution as you might run into problems otherwise. Try something like cd $(echo a b c) to see the problem.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .