Linux: How do I execute a script in a way that it knows its directory?

6

2

I need to write a script, which would be called from any location, but needs to run from the directory it resides in. The script should query its directory at runtime.

How can this be achieved?

Example:

  • script hello.sh resides in /someplace/
  • though it is called from /other/place/,
  • the script knows (during runtime) that it resides in /someplace

EDIT
Additional question:
How's about the location of the script, but with symlink resolved?

Example:

  • script hello.sh resides in /someplace/
  • symlink exists to it in /bin
  • though the symlink is called from /other/place/,
  • the script knows (during runtime) that it resides in /someplace

linux_is_for_desktop

Posted 2009-10-01T21:54:01.413

Reputation: 678

I suggest you move this to Stackoverflow. I think it's more related to programming than to general computing, and you might get faster and better responses there. – Nathan Fellman – 2009-10-01T21:59:24.850

Answers

5

echo $(dirname $0)

or

echo ${0%/*}

Paused until further notice.

Posted 2009-10-01T21:54:01.413

Reputation: 86 075

Great, it works! – linux_is_for_desktop – 2009-10-01T22:05:42.247

1Unless the script is in your PATH and you don't specify the full path to it; in that case, $0 will not have any path information. The best you can do then is to traverse PATH yourself. – wfaulk – 2009-10-01T22:08:38.077

"Unless the script is in your PATH" - I just tested this and got the correct result. The worst case is if you do ./scriptname then you just get back ., but you can test for that and get $PWD or $(pwd). – Paused until further notice. – 2009-10-01T22:18:08.837

Also, if you have readlink, you can do stuff like readlink -f .. to turn relative paths into absolute ones. – Paused until further notice. – 2009-10-01T22:20:56.863

2

To my additional question: I found this to work:

echo $(dirname $(readlink $0))

or

echo `dirname \`readlink $0\``

EDIT
Seems, this answer came at the same time Dennis Williamson commented his answer with the solution ;)

linux_is_for_desktop

Posted 2009-10-01T21:54:01.413

Reputation: 678

You can (and should) nest $(), so this would be echo $(dirname $(readlink $0)) – Paused until further notice. – 2009-10-01T22:22:17.657

Can you explain why, please? – linux_is_for_desktop – 2009-10-01T22:23:00.417

The second one would be parsed as echo dirname \ then readlink $0 then `` It has no way of knowing that the first should match the fourth. With $( and ) it knows what matches what. – Randy Orrison – 2009-10-01T22:52:10.717

That mangled the backquotes. It should have been echo (backquote dirname backslash backquote) then (readlink $0) then (backquote backquote). It has no way of knowing that the first backquote should match the fourth backquote, so it just matches the first with the second, and the third with with fourth. – Randy Orrison – 2009-10-01T22:54:15.767

Readability, nestability, reduced need for escaping, etc.: http://mywiki.wooledge.org/BashFAQ/082

– Paused until further notice. – 2009-10-02T00:24:00.247

1

Check out the shell variable $_

From the bash manpage:

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. 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 checking mail, this parameter holds the name of the mail file currently being checked.

jakob

Posted 2009-10-01T21:54:01.413

Reputation: 241