4

Is there a less brute-force way to do this?

#!/bin/ksh
THIS_SCRIPT=$(/usr/bin/readlink -f $(echo $0 | /bin/sed "s,^[^/],$PWD/&,"))
echo $THIS_SCRIPT

I'm stuck using ksh but would prefer a solution that works in bash too (which I think this does).

Dan
  • 5,929
  • 6
  • 42
  • 52
  • @Carl: not sure what you mean. $0 is the name of the script, but may be an absolute path or relative. – Dan Mar 17 '10 at 19:20
  • you're right - you only care about the pathname for the one getting executed. Deleting the other comments. – Carl Norum Mar 17 '10 at 19:25
  • @Carl, actually I thought you had a good point about hard links. I hadn't thought about them. – Dan Mar 17 '10 at 19:29
  • yeah they're a rare case though. For the purposes you're looking for they don't really matter, right? Any one good path is ok, and in particular the pathname being executed will be found with your check, so that should be good. – Carl Norum Mar 17 '10 at 19:41
  • Does this answer your question? [How to get the source directory of a Bash script from within the script itself](https://stackoverflow.com/questions/59895/how-to-get-the-source-directory-of-a-bash-script-from-within-the-script-itself) – Toby Speight Mar 05 '20 at 18:28

4 Answers4

7

Entry #28 in the bash FAQ:

How do I determine the location of my script? I want to read some config files from the same place.

There are two prime reasons why this issue comes up: either you want to externalize data or configuration of your script and need a way to find these external resources, or your script is intended to act upon a bundle of some sort (eg. a build script), and needs to find the resources to act upon.

It is important to realize that in the general case, this problem has no solution. Any approach you might have heard of, and any approach that will be detailed below, has flaws and will only work in specific cases. First and foremost, try to avoid the problem entirely by not depending on the location of your script!

...

Using BASH_SOURCE

The BASH_SOURCE internal bash variable is actually an array of pathnames. If you expand it as a simple string, e.g. "$BASH_SOURCE", you'll get the first element, which is the pathname of the currently executing function or script.

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Wow... I really didn't want to go down the rabbit hole that far, but that's a great answer. I'm going to stick with my `readlink` solution because it's good enough for what I'm doing, but I'll accept this answer. – Dan Mar 17 '10 at 19:31
  • This would be a much better answer with a summary of the entry. – DJClayworth Mar 13 '14 at 01:04
5

I've always done:

SCRIPT_PATH=$(cd `dirname ${0}`; pwd)

I've never used readlink before: is it Gnu only? (i.e. will it work on HP-UX, AIX, and Solaris out of the box? dirname and pwd will....)

(edited to add `` which I forgot in original post. d'oh!) (edit 2 to put on two lines which I've apparently always done when I look at previous scripts I'd written, but hadn't remembered properly. First call gets path, second call eliminates relative path) (edit 3 fixed typo that prevented single line answer from working, back to single line!)

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
Dana Lacoste
  • 179
  • 1
  • 7
4

Why didn't I think to try this before I asked the question?

THIS_SCRIPT=$(/usr/bin/readlink -nf "$0")

Works great.

Dan
  • 5,929
  • 6
  • 42
  • 52
0

In macOS I use (edit: only works if you run the script from where the script actually is!)

my_script=$(pwd)/$(basename $0)

Claudio
  • 5,740
  • 5
  • 33
  • 40