30

Suppose I have a bash file called myBash.bash. It resides in:

/myDirect/myFolder/myBash.bash

Now I want to use the string /myDirect/myFolder (the location of myBash.bash) inside the script. Is there a command I can use to find this location?

Edit: The idea is that I want to set-up a zip-folder with code that can be started by a bash script inside that zip-file. I know the relative file-paths of the code inside that zip-file, but not the absolute paths, and I need those. One way would be to hard-code in the path, or require the path of the file to be given as a variable. However I would find it easier if it was possible for the bash-file to figure out where it is on its own and then create the relevant paths to the other file from its knowledge of the structure of the zip-file.

Zanna
  • 70,465
dimpol
  • 499
  • 4
    This might be better suited for stackoverflow. Check these questions: http://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself http://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within. – Sethos II Mar 17 '17 at 08:41
  • 1
    use how.? please clarify – Sergiy Kolodyazhnyy Mar 17 '17 at 08:46
  • 1
    @SethosII this question is totally on topic here – Zanna Mar 17 '17 at 08:47
  • @Zanna pwd returns your current directory (from where you run the scirpt) not the scripts location. And just for clarification: it's about bash scripting, which is part of ubuntu, but isn't it more about programming then the distribution itself? – Sethos II Mar 17 '17 at 08:52
  • 1
    I added more context to the question. I thought there might be an easy/obvious command to get the file-path of the file that is executing, but it seems the answer is at least non-obvious. – dimpol Mar 17 '17 at 09:10
  • 3
    @Zanna I don't say it's offtopic, i think it's just more appropriate and as shown with the links already asked and answered there multiple times. – Sethos II Mar 17 '17 at 09:16
  • Thanks for the help everyone! The answer is indeed to take the zeroth argument of the bash-file and then use functions like dirname and realpath to get where you want to be. My apologies that I wasn't able to find the previous questions on this topic – dimpol Mar 17 '17 at 09:30
  • 1
    Questions that have been answered 8 years ago on StackOverflow, have been viewed about a million times, and have over 4000 upvotes aren't very suited to post here. Well I guess it's not a duplicate here. – laurent Mar 17 '17 at 15:46
  • Please note that sometimes there is no path. For example: cat /foo/bar | bash. – pipe Mar 17 '17 at 20:54

4 Answers4

44

You can get the full path like:

realpath "$0"

And as pointed out by Serg you can use dirname to strip the filename like this

dirname "$(realpath $0)"

or even better to prevent awkward quoting and word-splitting with difficult filenames:

temp=$( realpath "$0"  ) && dirname "$temp"

Much better than my earlier idea which was to parse it (I knew there would be a better way!)

realpath "$0" | sed 's|\(.*\)/.*|\1|'

Notes

  • realpath returns the actual path of a file
  • $0 is this file (the script)
  • s|old|new| replace old with new
  • \(.*\)/ save any characters before / for later
  • \1 the saved part
Zanna
  • 70,465
  • 3
    +1 for use of $0 and sed magic. But the said sed magic is really unnecessary when tools like dirname exist – Sergiy Kolodyazhnyy Mar 17 '17 at 09:42
  • 2
    you already have the answer , use realpath: realpath "$( dirname $0 )" I personally would use readlink but that's me: readlink -e $(dirname $0) – Sergiy Kolodyazhnyy Mar 17 '17 at 09:53
  • @Serg: Wouldn't dirname "$(realpath "$0")" be better? Usually one wants to know the parent directory of the referenced file instead of the parent directory of the symbolic link referring to said file. – David Foerster Mar 17 '17 at 14:22
  • 5
    @Serg "$(dirname "$(realpath "$0")")" is the most straightforward way. Quotes inside $() work as normal. – DepressedDaniel Mar 17 '17 at 20:01
  • @DepressedDaniel Did a bit of research online, you're right: $() being a subshell will allow having quotes outside. I wouldn't say it's as straightforward though, unless one realizes $() are all subshells – Sergiy Kolodyazhnyy Mar 17 '17 at 20:27
  • @DepressedDaniel has stated the actual most straightforward solution. – Wildcard Mar 18 '17 at 02:04
6

The accepted answer seems perfect. Here's another way to do it:

cd "$(dirname "$0")"
/bin/pwd

/bin/pwd prints the real path of the directory, as opposed to the pwd builtin command.

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
serv-inc
  • 3,059
5

if the script is in your path you can use something like

$ myloc=$(dirname "$(which foo.sh)")
$ echo "$myloc"
/path/to/foo.sh

EDIT: after reading comments from Serg, this might be a generic solution which works whether the script is in your path or not.

myloc==$(dirname "$(realpath $0)")
dirname "$myloc"
David Foerster
  • 36,264
  • 56
  • 94
  • 147
  • which is more suitable for when script resides in one of the directories that are part of PATH variable. Use $0 from within a script, just like Zanna shows. But your answer is proper since you use dirname instead of messing with sed, hence +1 for that – Sergiy Kolodyazhnyy Mar 17 '17 at 09:38
2
wdir="$PWD"; [ "$PWD" = "/" ] && wdir=""
case "$0" in
  /*) scriptdir="${0}";;
  *) scriptdir="$wdir/${0#./}";;
esac
scriptdir="${scriptdir%/*}"
echo "$scriptdir"

It is taken as reference from kenorb and andro
No dirname, readlink, realpath, BASH_SOURCE
All are builtins