<p>How do I get the path of the directory in which a <a href="http://en.wikipedia.org/wiki/Bash_%28Unix_shell%29" rel="noreferrer">Bash</a> script is located, <em>inside</em> that script?</p>
<p>I want to use a Bash script as a launcher for another application. I want to change the working directory to the one where the Bash script is located, so I can operate on the files in that directory, like so:</p>
<pre><code>$ ./application
</code></pre>

[{'answer_id': 59916, 'author': 'matt b', 'author_id': 4249, 'author_profile': 'https://Stackoverflow.com/users/4249', 'pm_score': 10, 'selected': False, 'text': '<p>Use <code>dirname &quot;$0&quot;</code>:</p>\n<pre><code>#!/usr/bin/env bash\n\necho &quot;The script you are running has basename $( basename -- &quot;$0&quot;; ), dirname $( dirname -- &quot;$0&quot;; )&quot;;\necho &quot;The present working directory is $( pwd; )&quot;;\n</code></pre>\n<p>Using <code>pwd</code> alone will not work if you are not running the script from the directory it is contained in.</p>\n<pre><code>[matt@server1 ~]$ pwd\n/home/matt\n[matt@server1 ~]$ ./test2.sh\nThe script you are running has basename test2.sh, dirname .\nThe present working directory is /home/matt\n[matt@server1 ~]$ cd /tmp\n[matt@server1 tmp]$ ~/test2.sh\nThe script you are running has basename test2.sh, dirname /home/matt\nThe present working directory is /tmp\n</code></pre>\n'}, {'answer_id': 59921, 'author': 'Mr Shark', 'author_id': 6093, 'author_profile': 'https://Stackoverflow.com/users/6093', 'pm_score': 7, 'selected': False, 'text': "<p>You can use <code>$BASH_SOURCE</code>:</p>\n<pre><code>#!/usr/bin/env bash\n\nscriptdir=&quot;$( dirname -- &quot;$BASH_SOURCE&quot;; )&quot;;\n</code></pre>\n<p>Note that you need to use <code>#!/bin/bash</code> and not <code>#!/bin/sh</code> since it's a Bash extension.</p>\n"}, {'answer_id': 60232, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 5, 'selected': False, 'text': "<p>I don't think this is as easy as others have made it out to be.  <code>pwd</code> doesn't work, as the current directory is not necessarily the directory with the script.  <code>$0</code> doesn't always have the information either.  Consider the following three ways to invoke a script:</p>\n\n<pre><code>./script\n\n/usr/bin/script\n\nscript\n</code></pre>\n\n<p>In the first and third ways <code>$0</code> doesn't have the full path information.  In the second and third, <code>pwd</code> does not work.  The only way to get the directory in the third way would be to run through the path and find the file with the correct match.  Basically the code would have to redo what the OS does.</p>\n\n<p>One way to do what you are asking would be to just hardcode the data in the <code>/usr/share</code> directory, and reference it by its full path.  Data shoudn't be in the <code>/usr/bin</code> directory anyway, so this is probably the thing to do.</p>\n"}, {'answer_id': 60247, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 4, 'selected': False, 'text': '<pre><code>#!/bin/sh\nPRG="$0"\n\n# need this for relative symlinks\nwhile [ -h "$PRG" ] ; do\n   PRG=`readlink "$PRG"`\ndone\n\nscriptdir=`dirname "$PRG"`\n</code></pre>\n'}, {'answer_id': 66271, 'author': 'SpoonMeiser', 'author_id': 1577190, 'author_profile': 'https://Stackoverflow.com/users/1577190', 'pm_score': 6, 'selected': False, 'text': "<p><code>pwd</code> can be used to find the current working directory, and <code>dirname</code> to find the directory of a particular file (command that was run, is <code>$0</code>, so <code>dirname $0</code> should give you the directory of the current script).</p>\n<p>However, <code>dirname</code> gives precisely the directory portion of the filename, which more likely than not is going to be relative to the current working directory. If your script needs to change directory for some reason, then the output from <code>dirname</code> becomes meaningless.</p>\n<p>I suggest the following:</p>\n<pre><code>#!/usr/bin/env bash\n\nreldir=&quot;$( dirname -- &quot;$0&quot;; )&quot;;\ncd &quot;$reldir&quot;;\ndirectory=&quot;$( pwd; )&quot;;\n\necho &quot;Directory is ${directory}&quot;;\n</code></pre>\n<p>This way, you get an absolute, rather than a relative directory.</p>\n<p>Since the script will be run in a separate Bash instance, there isn't any need to restore the working directory afterwards, but if you do want to change back in your script for some reason, you can easily assign the value of <code>pwd</code> to a variable before you change directory, for future use.</p>\n<p>Although just</p>\n<pre><code>cd &quot;$( dirname -- &quot;$0&quot;; )&quot;;\n</code></pre>\n<p>solves the specific scenario in the question, I find having the absolute path to more more useful generally.</p>\n"}, {'answer_id': 76257, 'author': 'Steve Baker', 'author_id': 13566, 'author_profile': 'https://Stackoverflow.com/users/13566', 'pm_score': 5, 'selected': False, 'text': '<p>This is Linux specific, but you could use:</p>\n\n<pre><code>SELF=$(readlink /proc/$$/fd/255)\n</code></pre>\n'}, {'answer_id': 179231, 'author': 'user25866', 'author_id': 25866, 'author_profile': 'https://Stackoverflow.com/users/25866', 'pm_score': 8, 'selected': False, 'text': "<pre><code>pushd . &gt; '/dev/null';\nSCRIPT_PATH=&quot;${BASH_SOURCE[0]:-$0}&quot;;\n\nwhile [ -h &quot;$SCRIPT_PATH&quot; ];\ndo\n    cd &quot;$( dirname -- &quot;$SCRIPT_PATH&quot;; )&quot;;\n    SCRIPT_PATH=&quot;$( readlink -f -- &quot;$SCRIPT_PATH&quot;; )&quot;;\ndone\n\ncd &quot;$( dirname -- &quot;$SCRIPT_PATH&quot;; )&quot; &gt; '/dev/null';\nSCRIPT_PATH=&quot;$( pwd; )&quot;;\npopd  &gt; '/dev/null';\n</code></pre>\n<p>It works for all versions, including</p>\n<ul>\n<li>when called via multiple depth soft link,</li>\n<li>when the file it</li>\n<li>when script called by command &quot;<code>source</code>&quot; aka <code>.</code> (dot) operator.</li>\n<li>when arg <code>$0</code> is modified from caller.</li>\n<li><code>&quot;./script&quot;</code></li>\n<li><code>&quot;/full/path/to/script&quot;</code></li>\n<li><code>&quot;/some/path/../../another/path/script&quot;</code></li>\n<li><code>&quot;./some/folder/script&quot;</code></li>\n</ul>\n<p>Alternatively, if the Bash script itself is a <strong>relative symlink</strong> you <em>want</em> to follow it and return the full path of the linked-to script:</p>\n<pre><code>pushd . &gt; '/dev/null';\nSCRIPT_PATH=&quot;${BASH_SOURCE[0]:-$0}&quot;;\n\nwhile [ -h &quot;$SCRIPT_PATH&quot; ];\ndo\n    cd &quot;$( dirname -- &quot;$SCRIPT_PATH&quot;; )&quot;;\n    SCRIPT_PATH=&quot;$( readlink -f -- &quot;$SCRIPT_PATH&quot;; )&quot;;\ndone\n\ncd &quot;$( dirname -- &quot;$SCRIPT_PATH&quot;; )&quot; &gt; '/dev/null';\nSCRIPT_PATH=&quot;$( pwd; )&quot;;\npopd  &gt; '/dev/null';\n</code></pre>\n<p><code>SCRIPT_PATH</code> is given in full path, no matter how it is called.</p>\n<p>Just make sure you locate this at start of the script.</p>\n"}, {'answer_id': 201915, 'author': 'Matt Tardiff', 'author_id': 27925, 'author_profile': 'https://Stackoverflow.com/users/27925', 'pm_score': 4, 'selected': False, 'text': "<p>This works in Bash 3.2:</p>\n<pre><code>path=&quot;$( dirname &quot;$( which &quot;$0&quot; )&quot; )&quot;\n</code></pre>\n<p>If you have a <code>~/bin</code> directory in your <code>$PATH</code>, you have  <code>A</code> inside this directory. It sources the script <code>~/bin/lib/B</code>. You know where the included script is relative to the original one, in the <code>lib</code> subdirectory, but not where it is relative to the user's current directory.</p>\n<p>This is solved by the following (inside <code>A</code>):</p>\n<pre><code>source &quot;$( dirname &quot;$( which &quot;$0&quot; )&quot; )/lib/B&quot;\n</code></pre>\n<p>It doesn't matter where the user is or how he/she calls the script. This will always work.</p>\n"}, {'answer_id': 246128, 'author': 'dogbane', 'author_id': 7412, 'author_profile': 'https://Stackoverflow.com/users/7412', 'pm_score': 14, 'selected': True, 'text': '<pre><code>#!/usr/bin/env bash\n\nSCRIPT_DIR=$( cd -- &quot;$( dirname -- &quot;${BASH_SOURCE[0]}&quot; )&quot; &amp;&gt; /dev/null &amp;&amp; pwd )\n</code></pre>\n<p>is a useful one-liner which will give you the full directory name of the script no matter where it is being called from.</p>\n<p>It will work as long as the last component of the path used to find the script is not a symlink (directory links are OK).  If you also want to resolve any links to the script itself, you need a multi-line solution:</p>\n<pre><code>#!/usr/bin/env bash\n\nSOURCE=${BASH_SOURCE[0]}\nwhile [ -L &quot;$SOURCE&quot; ]; do # resolve $SOURCE until the file is no longer a symlink\n  DIR=$( cd -P &quot;$( dirname &quot;$SOURCE&quot; )&quot; &gt;/dev/null 2&gt;&amp;1 &amp;&amp; pwd )\n  SOURCE=$(readlink &quot;$SOURCE&quot;)\n  [[ $SOURCE != /* ]] &amp;&amp; SOURCE=$DIR/$SOURCE # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located\ndone\nDIR=$( cd -P &quot;$( dirname &quot;$SOURCE&quot; )&quot; &gt;/dev/null 2&gt;&amp;1 &amp;&amp; pwd )\n</code></pre>\n<p>This last one will work with any combination of aliases, <code>source</code>, <code>bash -c</code>, symlinks, etc.</p>\n<p><strong>Beware:</strong> if you <code>cd</code> to a different directory before running this snippet, the result may be incorrect!</p>\n<p>Also, watch out for <a href="http://bosker.wordpress.com/2012/02/12/bash-scripters-beware-of-the-cdpath/" rel="noreferrer"><code>$CDPATH</code> gotchas</a>, and stderr output side effects if the user has smartly overridden cd to redirect output to stderr instead (including escape sequences, such as when calling <code>update_terminal_cwd &gt;&amp;2</code> on Mac). Adding <code>&gt;/dev/null 2&gt;&amp;1</code> at the end of your <code>cd</code> command will take care of both possibilities.</p>\n<p>To understand how it works, try running this more verbose form:</p>\n<pre><code>#!/usr/bin/env bash\n\nSOURCE=${BASH_SOURCE[0]}\nwhile [ -L &quot;$SOURCE&quot; ]; do # resolve $SOURCE until the file is no longer a symlink\n  TARGET=$(readlink &quot;$SOURCE&quot;)\n  if [[ $TARGET == /* ]]; then\n    echo &quot;SOURCE \'$SOURCE\' is an absolute symlink to \'$TARGET\'&quot;\n    SOURCE=$TARGET\n  else\n    DIR=$( dirname &quot;$SOURCE&quot; )\n    echo &quot;SOURCE \'$SOURCE\' is a relative symlink to \'$TARGET\' (relative to \'$DIR\')&quot;\n    SOURCE=$DIR/$TARGET # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located\n  fi\ndone\necho &quot;SOURCE is \'$SOURCE\'&quot;\nRDIR=$( dirname &quot;$SOURCE&quot; )\nDIR=$( cd -P &quot;$( dirname &quot;$SOURCE&quot; )&quot; &gt;/dev/null 2&gt;&amp;1 &amp;&amp; pwd )\nif [ &quot;$DIR&quot; != &quot;$RDIR&quot; ]; then\n  echo &quot;DIR \'$RDIR\' resolves to \'$DIR\'&quot;\nfi\necho &quot;DIR is \'$DIR\'&quot;\n</code></pre>\n<p>And it will print something like:</p>\n<pre class="lang-none prettyprint-override"><code>SOURCE \'./scriptdir.sh\' is a relative symlink to \'sym2/scriptdir.sh\' (relative to \'.\')\nSOURCE is \'./sym2/scriptdir.sh\'\nDIR \'./sym2\' resolves to \'/home/ubuntu/dotfiles/fo fo/real/real1/real2\'\nDIR is \'/home/ubuntu/dotfiles/fo fo/real/real1/real2\'\n</code></pre>\n'}, {'answer_id': 337006, 'author': 'Fabien', 'author_id': 21132, 'author_profile': 'https://Stackoverflow.com/users/21132', 'pm_score': 7, 'selected': False, 'text': '<p>Short answer:</p>\n<pre><code>&quot;`dirname -- &quot;$0&quot;;`&quot;\n</code></pre>\n<p>or (<a href="http://mywiki.wooledge.org/BashFAQ/082" rel="nofollow noreferrer">preferably</a>):</p>\n<pre><code>&quot;$( dirname -- &quot;$0&quot;; )&quot;\n</code></pre>\n'}, {'answer_id': 476266, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 0, 'selected': False, 'text': '<p>I usually do:</p>\n\n<pre><code>LIBDIR=$(dirname "$(readlink -f "$(type -P $0 || echo $0)")")\nsource $LIBDIR/lib.sh\n</code></pre>\n'}, {'answer_id': 476333, 'author': 'Joshua', 'author_id': 14768, 'author_profile': 'https://Stackoverflow.com/users/14768', 'pm_score': 3, 'selected': False, 'text': '<p>Hmm, if in the path, <a href="https://linux.die.net/man/1/basename" rel="nofollow noreferrer"><code>basename</code></a> and <a href="https://linux.die.net/man/1/dirname" rel="nofollow noreferrer"><code>dirname</code></a> are just not going to cut it and walking the path is hard (what if the parent didn\'t export PATH?!).</p>\n<p>However, the shell has to have an open handle to its script, and in Bash the handle is #255.</p>\n<pre><code>SELF=`readlink /proc/$$/fd/255`\n</code></pre>\n<p>works for me.</p>\n'}, {'answer_id': 541672, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': -1, 'selected': False, 'text': '<p>I want to make sure that the script is running in its directory. So</p>\n\n<pre><code>cd $(dirname $(which $0) )\n</code></pre>\n\n<p>After this, if you really want to know where the you are running then run the command below.</p>\n\n<pre><code>DIR=$(/usr/bin/pwd)\n</code></pre>\n'}, {'answer_id': 748265, 'author': 'BillTorpey', 'author_id': 62513, 'author_profile': 'https://Stackoverflow.com/users/62513', 'pm_score': 2, 'selected': False, 'text': '<p>This is the only way I\'ve found to tell reliably:</p>\n\n<pre><code>SCRIPT_DIR=$(dirname $(cd "$(dirname "$BASH_SOURCE")"; pwd))\n</code></pre>\n'}, {'answer_id': 1482133, 'author': 'phatblat', 'author_id': 39207, 'author_profile': 'https://Stackoverflow.com/users/39207', 'pm_score': 9, 'selected': False, 'text': '<p>The <a href="https://linux.die.net/man/1/dirname" rel="noreferrer"><code>dirname</code></a> command is the most basic, simply parsing the path up to the filename off of the <code>$0</code> (script name) variable:</p>\n<pre><code>dirname -- &quot;$0&quot;;\n</code></pre>\n<p>But, as <strong>matt b</strong> pointed out, the path returned is different depending on how the script is called. <code>pwd</code> doesn\'t do the job because that only tells you what the current directory is, not what directory the script resides in. Additionally, if a symbolic link to a script is executed, you\'re going to get a (probably relative) path to where the link resides, not the actual script.</p>\n<p>Some others have mentioned the <code>readlink</code> command, but at its simplest, you can use:</p>\n<pre><code>dirname -- &quot;$( readlink -f -- &quot;$0&quot;; )&quot;;\n</code></pre>\n<p><code>readlink</code> will resolve the script path to an absolute path from the root of the filesystem. So, any paths containing single or double dots, tildes and/or symbolic links will be resolved to a full path.</p>\n<p>Here\'s a script demonstrating each of these, <code>whatdir.sh</code>:</p>\n<pre><code>#!/usr/bin/env bash\n\necho &quot;pwd: `pwd`&quot;\necho &quot;\\$0: $0&quot;\necho &quot;basename: `basename -- &quot;$0&quot;`&quot;\necho &quot;dirname: `dirname -- &quot;$0&quot;`&quot;\necho &quot;dirname/readlink: $( dirname -- &quot;$( readlink -f -- &quot;$0&quot;; )&quot;; )&quot;\n</code></pre>\n<p>Running this script in my home dir, using a relative path:</p>\n<pre class="lang-none prettyprint-override"><code>&gt;&gt;&gt;$ ./whatdir.sh\npwd: /Users/phatblat\n$0: ./whatdir.sh\nbasename: whatdir.sh\ndirname: .\ndirname/readlink: /Users/phatblat\n</code></pre>\n<p>Again, but using the full path to the script:</p>\n<pre class="lang-none prettyprint-override"><code>&gt;&gt;&gt;$ /Users/phatblat/whatdir.sh\npwd: /Users/phatblat\n$0: /Users/phatblat/whatdir.sh\nbasename: whatdir.sh\ndirname: /Users/phatblat\ndirname/readlink: /Users/phatblat\n</code></pre>\n<p>Now changing directories:</p>\n<pre class="lang-none prettyprint-override"><code>&gt;&gt;&gt;$ cd /tmp\n&gt;&gt;&gt;$ ~/whatdir.sh\npwd: /tmp\n$0: /Users/phatblat/whatdir.sh\nbasename: whatdir.sh\ndirname: /Users/phatblat\ndirname/readlink: /Users/phatblat\n</code></pre>\n<p>And finally using a symbolic link to execute the script:</p>\n<pre class="lang-none prettyprint-override"><code>&gt;&gt;&gt;$ ln -s ~/whatdir.sh whatdirlink.sh\n&gt;&gt;&gt;$ ./whatdirlink.sh\npwd: /tmp\n$0: ./whatdirlink.sh\nbasename: whatdirlink.sh\ndirname: .\ndirname/readlink: /Users/phatblat\n</code></pre>\n<p>There is however one case where this doesn\'t work, when the script is sourced (instead of executed) in bash:</p>\n<pre class="lang-none prettyprint-override"><code>&gt;&gt;&gt;$ cd /tmp\n&gt;&gt;&gt;$ . ~/whatdir.sh  \npwd: /tmp\n$0: bash\nbasename: bash\ndirname: .\ndirname/readlink: /tmp\n</code></pre>\n'}, {'answer_id': 1815323, 'author': 'Stefano Borini', 'author_id': 78374, 'author_profile': 'https://Stackoverflow.com/users/78374', 'pm_score': -1, 'selected': False, 'text': '<pre><code>function getScriptAbsoluteDir { # fold&gt;&gt;\n    # @description used to get the script path\n    # @param $1 the script $0 parameter\n    local script_invoke_path="$1"\n    local cwd=`pwd`\n\n    # absolute path ? if so, the first character is a /\n    if test "x${script_invoke_path:0:1}" = \'x/\'\n    then\n        RESULT=`dirname "$script_invoke_path"`\n    else\n        RESULT=`dirname "$cwd/$script_invoke_path"`\n    fi\n} # &lt;&lt;fold\n</code></pre>\n'}, {'answer_id': 2633580, 'author': 'Fuwjax', 'author_id': 315943, 'author_profile': 'https://Stackoverflow.com/users/315943', 'pm_score': 4, 'selected': False, 'text': '<p>This is a slight revision to the solution e-satis and 3bcdnlklvc04a pointed out in <a href="https://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-in/179231#179231" title="their answer">their answer</a>:</p>\n<pre><code>SCRIPT_DIR=\'\'\npushd &quot;$(dirname &quot;$(readlink -f &quot;$BASH_SOURCE&quot;)&quot;)&quot; &gt; /dev/null &amp;&amp; {\n    SCRIPT_DIR=&quot;$PWD&quot;\n    popd &gt; /dev/null\n}\n</code></pre>\n<p>This should still work in all the cases they listed.</p>\n<p>This will prevent <code>popd</code> after a failed <code>pushd</code>. Thanks to konsolebox.</p>\n'}, {'answer_id': 3674520, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 4, 'selected': False, 'text': "<p>I tried all of these and none worked. One was very close, but it had a tiny bug that broke it badly; they forgot to wrap the path in quotation marks.</p>\n<p>Also a lot of people assume you're running the script from a shell, so they forget when you open a new script it defaults to your home.</p>\n<p>Try this directory on for size:</p>\n<pre><code>/var/No one/Thought/About Spaces Being/In a Directory/Name/And Here's your file.text\n</code></pre>\n<p>This gets it right regardless how or where you run it:</p>\n<pre><code>#!/bin/bash\necho &quot;pwd: `pwd`&quot;\necho &quot;\\$0: $0&quot;\necho &quot;basename: `basename &quot;$0&quot;`&quot;\necho &quot;dirname: `dirname &quot;$0&quot;`&quot;\n</code></pre>\n<p>So to make it actually useful, here's how to change to the directory of the running script:</p>\n<pre><code>cd &quot;`dirname &quot;$0&quot;`&quot;\n</code></pre>\n"}, {'answer_id': 3774351, 'author': 'tigfox', 'author_id': 455644, 'author_profile': 'https://Stackoverflow.com/users/455644', 'pm_score': 3, 'selected': False, 'text': '<p>None of these other answers worked for a Bash script launched by <a href="https://en.wikipedia.org/wiki/Finder_(software)" rel="nofollow noreferrer">Finder</a> in <a href="https://en.wikipedia.org/wiki/Mac_OS_X" rel="nofollow noreferrer">OS\xa0X</a>. I ended up using:</p>\n<pre><code>SCRIPT_LOC=&quot;`ps -p $$ | sed /PID/d | sed s:.*/Network/:/Network/: |\nsed s:.*/Volumes/:/Volumes/:`&quot;\n</code></pre>\n<p>It is not pretty, but it gets the job done.</p>\n'}, {'answer_id': 3884245, 'author': 'P M', 'author_id': 396782, 'author_profile': 'https://Stackoverflow.com/users/396782', 'pm_score': 5, 'selected': False, 'text': '<pre><code>SCRIPT_DIR=$( cd ${0%/*} &amp;&amp; pwd -P )\n</code></pre>\n'}, {'answer_id': 3921651, 'author': 'alanwj', 'author_id': 60873, 'author_profile': 'https://Stackoverflow.com/users/60873', 'pm_score': 3, 'selected': False, 'text': '<p>Use a combination of <a href="https://linux.die.net/man/1/readlink" rel="nofollow noreferrer">readlink</a> to canonicalize the name (with a bonus of following it back to its source if it is a symlink) and <a href="https://linux.die.net/man/1/dirname" rel="nofollow noreferrer">dirname</a> to extract the directory name:</p>\n<pre><code>script=&quot;`readlink -f &quot;${BASH_SOURCE[0]}&quot;`&quot;\ndir=&quot;`dirname &quot;$script&quot;`&quot;\n</code></pre>\n'}, {'answer_id': 4560790, 'author': 'Pubguy', 'author_id': 558024, 'author_profile': 'https://Stackoverflow.com/users/558024', 'pm_score': 5, 'selected': False, 'text': '<p>This gets the current working directory on <a href="https://en.wikipedia.org/wiki/Mac_OS_X_Snow_Leopard" rel="noreferrer">Mac\xa0OS\xa0X\xa0v10.6.6</a> (Snow\xa0Leopard):</p>\n<pre><code>DIR=$(cd &quot;$(dirname &quot;$0&quot;)&quot;; pwd)\n</code></pre>\n'}, {'answer_id': 6840978, 'author': 'test11', 'author_id': 864899, 'author_profile': 'https://Stackoverflow.com/users/864899', 'pm_score': 5, 'selected': False, 'text': '<pre><code>$(dirname "$(readlink -f "$BASH_SOURCE")")\n</code></pre>\n'}, {'answer_id': 7449270, 'author': 'hurrymaplelad', 'author_id': 407845, 'author_profile': 'https://Stackoverflow.com/users/407845', 'pm_score': 4, 'selected': False, 'text': '<p><a href="http://www.gnu.org/s/bash/manual/bash.html#Environment" rel="nofollow noreferrer"><code>$_</code></a> is worth mentioning as an alternative to <code>$0</code>.  If you\'re running a script from Bash, the accepted answer can be shortened to:</p>\n\n<pre><code>DIR="$( dirname "$_" )"\n</code></pre>\n\n<p>Note that this has to be the first statement in your script.</p>\n'}, {'answer_id': 9158888, 'author': 'DarkPark', 'author_id': 1192073, 'author_profile': 'https://Stackoverflow.com/users/1192073', 'pm_score': 4, 'selected': False, 'text': '<p>Try using:</p>\n<pre><code>real=$(realpath &quot;$(dirname &quot;$0&quot;)&quot;)\n</code></pre>\n'}, {'answer_id': 13486116, 'author': 'Nicolas', 'author_id': 1433151, 'author_profile': 'https://Stackoverflow.com/users/1433151', 'pm_score': 4, 'selected': False, 'text': '<p>I would use something like this:</p>\n<pre><code># Retrieve the full pathname of the called script\nscriptPath=$(which $0)\n\n# Check whether the path is a link or not\nif [ -L $scriptPath ]; then\n\n    # It is a link then retrieve the target path and get the directory name\n    sourceDir=$(dirname $(readlink -f $scriptPath))\n\nelse\n\n    # Otherwise just get the directory name of the script path\n    sourceDir=$(dirname $scriptPath)\n\nfi\n</code></pre>\n'}, {'answer_id': 14881364, 'author': 'Zombo', 'author_id': 1002260, 'author_profile': 'https://Stackoverflow.com/users/1002260', 'pm_score': 0, 'selected': False, 'text': '<p>Here is a pure Bash solution</p>\n\n<pre><code>$ cat a.sh\nBASENAME=${BASH_SOURCE/*\\/}\nDIRNAME=${BASH_SOURCE%$BASENAME}.\necho $DIRNAME\n\n$ a.sh\n/usr/local/bin/.\n\n$ ./a.sh\n./.\n\n$ . a.sh\n/usr/local/bin/.\n\n$ /usr/local/bin/a.sh\n/usr/local/bin/.\n</code></pre>\n'}, {'answer_id': 15255856, 'author': 'lamawithonel', 'author_id': 2044979, 'author_profile': 'https://Stackoverflow.com/users/2044979', 'pm_score': 5, 'selected': False, 'text': '<p>Here is a POSIX compliant one-liner:</p>\n\n<pre><code>SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \\"$SCRIPT_PATH\\" &amp;&amp; pwd"`\n\n# test\necho $SCRIPT_PATH\n</code></pre>\n'}, {'answer_id': 16131743, 'author': 'billyjmc', 'author_id': 558709, 'author_profile': 'https://Stackoverflow.com/users/558709', 'pm_score': 3, 'selected': False, 'text': '<p>I\'ve compared many of the answers given, and came up with some more compact solutions. These seem to handle all of the crazy edge cases that arise from your favorite combination of:</p>\n<ul>\n<li>Absolute paths or relative paths</li>\n<li>File and directory soft links</li>\n<li>Invocation as <code>script</code>, <code>bash script</code>, <code>bash -c script</code>, <code>source script</code>, or <code>. script</code></li>\n<li>Spaces, tabs, newlines, Unicode, etc. in directories and/or filename</li>\n<li>Filenames beginning with a hyphen</li>\n</ul>\n<p>If you\'re running from Linux, it seems that using the <code>proc</code> handle is the best solution to locate the fully resolved source of the currently running script (in an interactive session, the link points to the respective <code>/dev/pts/X</code>):</p>\n<pre><code>resolved=&quot;$(readlink /proc/$$/fd/255 &amp;&amp; echo X)&quot; &amp;&amp; resolved=&quot;${resolved%$\'\\nX\'}&quot;\n</code></pre>\n<p>This has a small bit of ugliness to it, but the fix is compact and easy to understand. We aren\'t using bash primitives only, but I\'m okay with that because <a href="https://linux.die.net/man/1/readlink" rel="nofollow noreferrer"><code>readlink</code></a> simplifies the task considerably. The <code>echo X</code> adds an <code>X</code> to the end of the variable string so that any trailing whitespace in the filename doesn\'t get eaten, and the parameter substitution <code>${VAR%X}</code> at the end of the line gets rid of the <code>X</code>. Because <code>readlink</code> adds a newline of its own (which would normally be eaten in the command substitution if not for our previous trickery), we have to get rid of that, too. This is most easily accomplished using the <code>$\'\'</code> quoting scheme, which lets us use escape sequences such as <code>\\n</code> to represent newlines (this is also how you can easily make deviously named directories and files).</p>\n<p>The above should cover your needs for locating the currently running script on Linux, but if you don\'t have the <code>proc</code> filesystem at your disposal, or if you\'re trying to locate the fully resolved path of some other file, then maybe you\'ll find the below code helpful. It\'s only a slight modification from the above one-liner. If you\'re playing around with strange directory/filenames, checking the output with both <code>ls</code> and <code>readlink</code> is informative, as <code>ls</code> will output &quot;simplified&quot; paths, substituting <code>?</code> for things like newlines.</p>\n<pre><code>absolute_path=$(readlink -e -- &quot;${BASH_SOURCE[0]}&quot; &amp;&amp; echo x) &amp;&amp; absolute_path=${absolute_path%?x}\ndir=$(dirname -- &quot;$absolute_path&quot; &amp;&amp; echo x) &amp;&amp; dir=${dir%?x}\nfile=$(basename -- &quot;$absolute_path&quot; &amp;&amp; echo x) &amp;&amp; file=${file%?x}\n\nls -l -- &quot;$dir/$file&quot;\nprintf \'$absolute_path: &quot;%s&quot;\\n\' &quot;$absolute_path&quot;\n</code></pre>\n'}, {'answer_id': 17011222, 'author': 'mproffitt', 'author_id': 2452553, 'author_profile': 'https://Stackoverflow.com/users/2452553', 'pm_score': -1, 'selected': False, 'text': '<p>I usually include the following at the top of my scripts which works in the majority of cases:</p>\n<pre><code>[ &quot;$(dirname $0)&quot; = \'.\' ] &amp;&amp; SOURCE_DIR=$(pwd) || SOURCE_DIR=$(dirname $0);\nls -l $0 | grep -q ^l &amp;&amp; SOURCE_DIR=$(ls -l $0 | awk \'{print $NF}\');\n</code></pre>\n<p>The first line assigns source based on the value of <code>pwd</code> if run from the current path or <a href="https://linux.die.net/man/1/dirname" rel="nofollow noreferrer">dirname</a> if called from elsewhere.</p>\n<p>The second line examines the path to see if it is a symlink and if so, updates SOURCE_DIR to the location of the link itself.</p>\n<p>There are probably better solutions out there, but this is the cleanest I\'ve managed to come up with myself.</p>\n'}, {'answer_id': 19153434, 'author': 'AsymLabs', 'author_id': 2839332, 'author_profile': 'https://Stackoverflow.com/users/2839332', 'pm_score': -1, 'selected': False, 'text': '<p>Try something like this:</p>\n<pre><code>function get_realpath() {\n\nif [[ -f &quot;$1&quot; ]]\nthen\n    # The file *must* exist\n    if cd &quot;$(echo &quot;${1%/*}&quot;)&quot; &amp;&gt;/dev/null\n    then\n        # The file *may* not be local.\n        # The exception is ./file.ext\n        # tTry \'cd .; cd -;\' *works!*\n        local tmppwd=&quot;$PWD&quot;\n        cd - &amp;&gt;/dev/null\n    else\n        # file *must* be local\n        local tmppwd=&quot;$PWD&quot;\n    fi\nelse\n    # The file *cannot* exist\n    return 1 # Failure\nfi\n\n# Reassemble realpath\necho &quot;$tmppwd&quot;/&quot;${1##*/}&quot;\nreturn 0 # Success\n\n}\n\nfunction get_dirname(){\n\nlocal realpath=&quot;$(get_realpath &quot;$1&quot;)&quot;\nif (( $? )) # True when non-zero.\nthen\n    return $? # Failure\nfi\necho &quot;${realpath%/*}&quot;\nreturn 0 # Success\n\n}\n\n# Then from the top level:\nget_dirname \'./script.sh\'\n\n# Or within a script:\nget_dirname &quot;$0&quot;\n\n# Can even test the outcome!\nif (( $? )) # True when non-zero.\nthen\n    exit 1 # Failure\nfi\n</code></pre>\n<p>These functions and related tools are part of our product that has been made available to the community for free and can be found at GitHub as <a href="http://asymlabs.github.io/realpath-lib/" rel="nofollow noreferrer">realpath-lib</a>.  It\'s simple, clean and well documented (great for learning), pure Bash and has no dependencies. Good for cross-platform use too.  So for the above example, within a script you could simply:</p>\n<pre><code>source \'/path/to/realpath-lib\'\n\nget_dirname &quot;$0&quot;\n\nif (( $? )) # True when non-zero.\nthen\n    exit 1 # Failure\nfi\n</code></pre>\n'}, {'answer_id': 19250386, 'author': 'AsymLabs', 'author_id': 2839332, 'author_profile': 'https://Stackoverflow.com/users/2839332', 'pm_score': 3, 'selected': False, 'text': '<p>The best compact solution in my view would be:</p>\n<pre><code>&quot;$( cd &quot;$( echo &quot;${BASH_SOURCE[0]%/*}&quot; )&quot;; pwd )&quot;\n</code></pre>\n<p>There is no reliance on anything other than Bash.  The use of <a href="https://linux.die.net/man/1/dirname" rel="nofollow noreferrer"><code>dirname</code></a>, <a href="https://linux.die.net/man/1/readlink" rel="nofollow noreferrer"><code>readlink</code></a> and <a href="https://linux.die.net/man/1/basename" rel="nofollow noreferrer"><code>basename</code></a> will eventually lead to compatibility issues, so they are best avoided if at all possible.</p>\n'}, {'answer_id': 20228026, 'author': 'mikeserv', 'author_id': 2955202, 'author_profile': 'https://Stackoverflow.com/users/2955202', 'pm_score': 0, 'selected': False, 'text': '<p>Here\'s an excerpt from my answer to <a href="https://stackoverflow.com/questions/12690085/shell-script-check-directory-name-and-convert-to-lowercase/20227287#20227287">shell script: check directory name and convert to lowercase</a> in which I demonstrate not only how to solve this problem with very basic POSIX-specified utilities, I also address <em><strong>how to very simply store the function\'s results in a returned variable...</strong></em></p>\n<p>...Well, as you can see, with <strong>some help</strong>, I hit upon a pretty simple and very powerful solution:</p>\n<p>I can pass the function a sort of <em>messenger variable</em> and dereference any explicit use of the resulting function\'s argument\'s <code>$1</code> name with <code>eval</code> as necessary, and, upon the function routine\'s completion, I use <code>eval</code> and a backslashed quoting trick to assign my messenger variable the value I desire without ever having to know its name.</p>\n<p>In full disclosure, ... (I found the messenger variable portion of this) and at <a href="http://www.etalabs.net/sh_tricks.html" rel="nofollow noreferrer">Rich\'s sh tricks</a> and I have also excerpted the relevant portion of his page below my own answer\'s excerpt.</p>\n<p>...\n<strong>EXCERPT:</strong>\n...</p>\n<p>Though not strictly POSIX yet, <strong><a href="http://www.gnu.org/software/coreutils/manual/html_node/realpath-invocation.html" rel="nofollow noreferrer">realpath</a> is a GNU core application since 2012</strong>. Full disclosure: never heard of it before I noticed it in the <code>info coreutils</code> TOC and immediately thought of [the linked] question, but using the following function as demonstrated should reliably, (soon POSIXLY?), and, I hope, efficiently\nprovide its caller with an absolutely sourced <code>$0</code>:</p>\n<pre><code>% _abs_0() {\n&gt; o1=&quot;${1%%/*}&quot;; ${o1:=&quot;${1}&quot;}; ${o1:=`realpath -s &quot;${1}&quot;`}; eval &quot;$1=\\${o1}&quot;;\n&gt; }\n% _abs_0 ${abs0:=&quot;${0}&quot;} ; printf %s\\\\n &quot;${abs0}&quot;\n/no/more/dots/in/your/path2.sh\n</code></pre>\n<p>It may be worth highlighting that this solution uses <a href="http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02" rel="nofollow noreferrer">POSIX parameter expansion</a> to first check if the path actually needs expanding and resolving at all before attempting to do so. This should <strong>return an absolutely sourced <code>$0</code>via a messenger variable</strong> <em>(with the notable exception that it will preserve <code>symlinks</code>)</em> as <strong>efficiently</strong> as I could imagine it could be done <strong>whether or not the path is already absolute.</strong>\n...</p>\n<p>(<em><strong>minor edit</strong>: before finding <code>realpath</code> in the docs, I had at least pared down my version of (the version below) not to depend on the time field (as it does in the first <code>ps</code> command), but, fair warning, after testing some I\'m less convinced <code>ps</code> is fully reliable in its command path expansion capacity</em>)</p>\n<p>On the other hand, you could do this:</p>\n<pre><code>ps ww -fp $$ | grep -Eo \'/[^:]*\'&quot;${0#*/}&quot;\n\neval &quot;abs0=${`ps ww -fp $$ | grep -Eo \' /\'`#?}&quot;\n</code></pre>\n<p>...\n<strong>And from <a href="http://www.etalabs.net/sh_tricks.html" rel="nofollow noreferrer">Rich\'s sh tricks</a>:</strong>\n...</p>\n<p><strong>Returning strings from a shell function</strong></p>\n<p>As can be seen from the above pitfall of command substitution, standard output is not a good avenue for shell functions to return strings to their caller, unless the output is in a format where trailing newlines are insignificant. Certainly such practice is not acceptable for functions meant to deal with arbitrary strings. So, what can be done?</p>\n<p>Try this:</p>\n<pre><code>func () {\nbody here\neval &quot;$1=\\${foo}&quot;\n}\n</code></pre>\n<p>Of course, <code>${foo}</code> could be replaced by any sort of substitution. The key trick here is the eval line and the use of escaping. The <code>“$1”</code> is expanded when the argument to eval is constructed by the main command parser. But the <code>“${foo}”</code> is not expanded at this stage, because the <code>“$”</code> has been quoted. Instead, it’s expanded when eval evaluates its argument. If it’s not clear why this is important, consider how the following would be bad:</p>\n<pre><code>foo=\'hello ; rm -rf /\'\ndest=bar\neval &quot;$dest=$foo&quot;\n</code></pre>\n<p>But of course the following version is perfectly safe:</p>\n<pre><code>foo=\'hello ; rm -rf /\'\ndest=bar\neval &quot;$dest=\\$foo&quot;\n</code></pre>\n<p>Note that in the original example, <code>“$1”</code> was used to allow the caller to pass the destination variable name as an argument the function. If your function needs to use the shift command, for instance to handle the remaining arguments as <code>“$@”</code>, then it may be useful to save the value of <code>“$1”</code> in a temporary variable at the beginning of the function.</p>\n'}, {'answer_id': 20265752, 'author': 'kenorb', 'author_id': 55075, 'author_profile': 'https://Stackoverflow.com/users/55075', 'pm_score': 3, 'selected': False, 'text': '<p>Try the following cross-compatible solution:</p>\n<pre><code>CWD=&quot;$(cd -P -- &quot;$(dirname -- &quot;${BASH_SOURCE[0]}&quot;)&quot; &amp;&amp; pwd -P)&quot;\n</code></pre>\n<p>As the commands such as <code>realpath</code> or <code>readlink</code> could be not available (depending on the operating system).</p>\n<p>Note: In Bash, it\'s recommended to use <code>${BASH_SOURCE[0]}</code> instead of <code>$0</code>, otherwise path can break when sourcing the file (<code>source</code>/<code>.</code>).</p>\n<p>Alternatively you can try the following function in Bash:</p>\n<pre><code>realpath () {\n  [[ $1 = /* ]] &amp;&amp; echo &quot;$1&quot; || echo &quot;$PWD/${1#./}&quot;\n}\n</code></pre>\n<p>This function takes one argument. If argument has already absolute path, print it as it is, otherwise print <code>$PWD</code> variable + filename argument (without <code>./</code> prefix).</p>\n<p>Related:</p>\n<ul>\n<li><em><a href="https://stackoverflow.com/questions/3349105/how-to-set-current-working-directory-to-the-directory-of-the-script">How can I set the current working directory to the directory of the script in Bash?</a></em></li>\n<li><em><a href="https://stackoverflow.com/questions/3572030/bash-script-absolute-path-with-osx">Bash script absolute path with OS X</a></em></li>\n<li><em><a href="https://stackoverflow.com/questions/4774054/reliable-way-for-a-bash-script-to-get-the-full-path-to-itself/20265654#20265654">Reliable way for a Bash script to get the full path to itself</a></em></li>\n</ul>\n'}, {'answer_id': 20721819, 'author': 'Geoff Nixon', 'author_id': 2351351, 'author_profile': 'https://Stackoverflow.com/users/2351351', 'pm_score': 3, 'selected': False, 'text': '<p>I believe I\'ve got this one. I\'m late to the party, but I think some will appreciate it being here if they come across this thread. The comments should explain:</p>\n\n<pre><code>#!/bin/sh # dash bash ksh # !zsh (issues). G. Nixon, 12/2013. Public domain.\n\n## \'linkread\' or \'fullpath\' or (you choose) is a little tool to recursively\n## dereference symbolic links (ala \'readlink\') until the originating file\n## is found. This is effectively the same function provided in stdlib.h as\n## \'realpath\' and on the command line in GNU \'readlink -f\'.\n\n## Neither of these tools, however, are particularly accessible on the many\n## systems that do not have the GNU implementation of readlink, nor ship\n## with a system compiler (not to mention the requisite knowledge of C).\n\n## This script is written with portability and (to the extent possible, speed)\n## in mind, hence the use of printf for echo and case statements where they\n## can be substituded for test, though I\'ve had to scale back a bit on that.\n\n## It is (to the best of my knowledge) written in standard POSIX shell, and\n## has been tested with bash-as-bin-sh, dash, and ksh93. zsh seems to have\n## issues with it, though I\'m not sure why; so probably best to avoid for now.\n\n## Particularly useful (in fact, the reason I wrote this) is the fact that\n## it can be used within a shell script to find the path of the script itself.\n## (I am sure the shell knows this already; but most likely for the sake of\n## security it is not made readily available. The implementation of "$0"\n## specificies that the $0 must be the location of **last** symbolic link in\n## a chain, or wherever it resides in the path.) This can be used for some\n## ...interesting things, like self-duplicating and self-modifiying scripts.\n\n## Currently supported are three errors: whether the file specified exists\n## (ala ENOENT), whether its target exists/is accessible; and the special\n## case of when a sybolic link references itself "foo -&gt; foo": a common error\n## for beginners, since \'ln\' does not produce an error if the order of link\n## and target are reversed on the command line. (See POSIX signal ELOOP.)\n\n## It would probably be rather simple to write to use this as a basis for\n## a pure shell implementation of the \'symlinks\' util included with Linux.\n\n## As an aside, the amount of code below **completely** belies the amount\n## effort it took to get this right -- but I guess that\'s coding for you.\n\n##===-------------------------------------------------------------------===##\n\nfor argv; do :; done # Last parameter on command line, for options parsing.\n\n## Error messages. Use functions so that we can sub in when the error occurs.\n\nrecurses(){ printf "Self-referential:\\n\\t$argv -&gt;\\n\\t$argv\\n" ;}\ndangling(){ printf "Broken symlink:\\n\\t$argv -&gt;\\n\\t"$(readlink "$argv")"\\n" ;}\nerrnoent(){ printf "No such file: "$@"\\n" ;} # Borrow a horrible signal name.\n\n# Probably best not to install as \'pathfull\', if you can avoid it.\n\npathfull(){ cd "$(dirname "$@")"; link="$(readlink "$(basename "$@")")"\n\n## \'test and \'ls\' report different status for bad symlinks, so we use this.\n\n if [ ! -e "$@" ]; then if $(ls -d "$@" 2&gt;/dev/null) 2&gt;/dev/null;  then\n    errnoent 1&gt;&amp;2; exit 1; elif [ ! -e "$@" -a "$link" = "$@" ];   then\n    recurses 1&gt;&amp;2; exit 1; elif [ ! -e "$@" ] &amp;&amp; [ ! -z "$link" ]; then\n    dangling 1&gt;&amp;2; exit 1; fi\n fi\n\n## Not a link, but there might be one in the path, so \'cd\' and \'pwd\'.\n\n if [ -z "$link" ]; then if [ "$(dirname "$@" | cut -c1)" = \'/\' ]; then\n   printf "$@\\n"; exit 0; else printf "$(pwd)/$(basename "$@")\\n"; fi; exit 0\n fi\n\n## Walk the symlinks back to the origin. Calls itself recursivly as needed.\n\n while [ "$link" ]; do\n   cd "$(dirname "$link")"; newlink="$(readlink "$(basename "$link")")"\n   case "$newlink" in\n    "$link") dangling 1&gt;&amp;2 &amp;&amp; exit 1                                       ;;\n         \'\') printf "$(pwd)/$(basename "$link")\\n"; exit 0                 ;;\n          *) link="$newlink" &amp;&amp; pathfull "$link"                           ;;\n   esac\n done\n printf "$(pwd)/$(basename "$newlink")\\n"\n}\n\n## Demo. Install somewhere deep in the filesystem, then symlink somewhere \n## else, symlink again (maybe with a different name) elsewhere, and link\n## back into the directory you started in (or something.) The absolute path\n## of the script will always be reported in the usage, along with "$0".\n\nif [ -z "$argv" ]; then scriptname="$(pathfull "$0")"\n\n# Yay ANSI l33t codes! Fancy.\n printf "\\n\\033[3mfrom/as: \\033[4m$0\\033[0m\\n\\n\\033[1mUSAGE:\\033[0m   "\n printf "\\033[4m$scriptname\\033[24m [ link | file | dir ]\\n\\n         "\n printf "Recursive readlink for the authoritative file, symlink after "\n printf "symlink.\\n\\n\\n         \\033[4m$scriptname\\033[24m\\n\\n        "\n printf " From within an invocation of a script, locate the script\'s "\n printf "own file\\n         (no matter where it has been linked or "\n printf "from where it is being called).\\n\\n"\n\nelse pathfull "$@"\nfi\n</code></pre>\n'}, {'answer_id': 23846906, 'author': 'ideawu', 'author_id': 427640, 'author_profile': 'https://Stackoverflow.com/users/427640', 'pm_score': -1, 'selected': False, 'text': '<pre><code>cur_dir=`old=\\`pwd\\`; cd \\`dirname $0\\`; echo \\`pwd\\`; cd $old;`\n</code></pre>\n'}, {'answer_id': 23905052, 'author': 'user1338062', 'author_id': 1338062, 'author_profile': 'https://Stackoverflow.com/users/1338062', 'pm_score': 4, 'selected': False, 'text': "<p>For systems having GNU coreutils <code>readlink</code> (for example, Linux):</p>\n<pre><code>$(readlink -f &quot;$(dirname &quot;$0&quot;)&quot;)\n</code></pre>\n<p>There's no need to use <code>BASH_SOURCE</code> when <code>$0</code> contains the script filename.</p>\n"}, {'answer_id': 24545261, 'author': 'konsolebox', 'author_id': 445221, 'author_profile': 'https://Stackoverflow.com/users/445221', 'pm_score': -1, 'selected': False, 'text': '<p>No forks (besides subshell) and can handle "alien" pathname forms like those with newlines as some would claim:</p>\n\n<pre><code>IFS= read -rd \'\' DIR &lt; &lt;([[ $BASH_SOURCE != */* ]] || cd "${BASH_SOURCE%/*}/" &gt;&amp;- &amp;&amp; echo -n "$PWD")\n</code></pre>\n'}, {'answer_id': 25596764, 'author': 'gkb0986', 'author_id': 1988435, 'author_profile': 'https://Stackoverflow.com/users/1988435', 'pm_score': 2, 'selected': False, 'text': '<p>This solution applies only to Bash. Note that the commonly supplied answer <code>${BASH_SOURCE[0]}</code> won\'t work if you try to find the path from within a function.</p>\n<p>I\'ve found this line to always work, regardless of whether the file is being sourced or run as a script.</p>\n<pre><code>dirname ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}\n</code></pre>\n<p>If you want to follow symlinks use <a href="https://linux.die.net/man/1/readlink" rel="nofollow noreferrer"><code>readlink</code></a> on the path you get above, recursively or non-recursively.</p>\n<p>Here\'s a script to try it out and compare it to other proposed solutions. Invoke it as <code>source test1/test2/test_script.sh</code> or <code>bash test1/test2/test_script.sh</code>.</p>\n<pre><code>#\n# Location: test1/test2/test_script.sh\n#\necho $0\necho $_\necho ${BASH_SOURCE}\necho ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}\n\ncur_file=&quot;${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}&quot;\ncur_dir=&quot;$(dirname &quot;${cur_file}&quot;)&quot;\nsource &quot;${cur_dir}/func_def.sh&quot;\n\nfunction test_within_func_inside {\n    echo ${BASH_SOURCE}\n    echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}\n}\n\necho &quot;Testing within function inside&quot;\ntest_within_func_inside\n\necho &quot;Testing within function outside&quot;\ntest_within_func_outside\n\n#\n# Location: test1/test2/func_def.sh\n#\nfunction test_within_func_outside {\n    echo ${BASH_SOURCE}\n    echo ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}\n}\n</code></pre>\n<p>The reason the one-liner works is explained by the use of the <code>BASH_SOURCE</code> environment variable and its associated <code>FUNCNAME</code>.</p>\n<blockquote>\n<p>BASH_SOURCE</p>\n</blockquote>\n<blockquote>\n<p>An array variable whose members are the source filenames where the corresponding shell function names in the FUNCNAME array variable are  defined.  The shell function ${FUNCNAME[$i]} is defined in the file ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}.</p>\n</blockquote>\n<blockquote>\n<p>FUNCNAME</p>\n</blockquote>\n<blockquote>\n<p>An array variable containing the names of all shell functions currently in the execution call stack.  The element with index 0 is the name of  any currently-executing  shell  function.  The bottom-most element (the one with the highest index) is &quot;main&quot;.  This variable exists only when a shell function is executing.  Assignments to FUNCNAME doesn\'t have any effect and return an error status.  If FUNCNAME is unset, it loses its special properties, even if it is subsequently reset.</p>\n</blockquote>\n<blockquote>\n<p>This variable can be used with BASH_LINENO and BASH_SOURCE. Each element of FUNCNAME has corresponding elements in BASH_LINENO and BASH_SOURCE to describe the call stack. For instance, ${FUNCNAME[$i]} was called from the file ${BASH_SOURCE[$i+1]} at line number  ${BASH_LINENO[$i]}. The caller builtin displays the current call stack using this information.</p>\n</blockquote>\n<p>[Source: Bash manual]</p>\n'}, {'answer_id': 26934693, 'author': 'Paul Savage', 'author_id': 1901136, 'author_profile': 'https://Stackoverflow.com/users/1901136', 'pm_score': -1, 'selected': False, 'text': '<pre><code>FOLDERNAME=${PWD##*/}\n</code></pre>\n<p>That is the quickest way I know.</p>\n'}, {'answer_id': 33033257, 'author': 'michaeljt', 'author_id': 213180, 'author_profile': 'https://Stackoverflow.com/users/213180', 'pm_score': -1, 'selected': False, 'text': '<p>The key part is that I am reducing the scope of the problem: I forbid indirect execution of the script via the path (as in <code>/bin/sh [script path relative to path component]</code>).</p>\n<p>This can be detected because <code>$0</code> will be a relative path which does not resolve to any file relative to the current folder.  I believe that direct execution using the <code>#!</code> mechanism always results in an absolute <code>$0</code>, including when the script is found on the path.</p>\n<p>I also require that the pathname and any pathnames along a chain of symbolic links only contain a reasonable subset of characters, notably not <code>\\n</code>, <code>&gt;</code>, <code>*</code> or <code>?</code>.  This is required for the parsing logic.</p>\n<p>There are a few more implicit expectations which I will not go into (look at <a href="https://stackoverflow.com/a/4794711/213180">this answer</a>), and I do not attempt to handle deliberate sabotage of <code>$0</code> (so consider any security implications).  I expect this to work on almost any Unix-like system with a Bourne-like <code>/bin/sh</code>.</p>\n<pre><code>#!/bin/sh\n(\n    path=&quot;${0}&quot;\n    while test -n &quot;${path}&quot;; do\n        # Make sure we have at least one slash and no leading dash.\n        expr &quot;${path}&quot; : / &gt; /dev/null || path=&quot;./${path}&quot;\n        # Filter out bad characters in the path name.\n        expr &quot;${path}&quot; : &quot;.*[*?&lt;&gt;\\\\]&quot; &gt; /dev/null &amp;&amp; exit 1\n        # Catch embedded new-lines and non-existing (or path-relative) files.\n        # $0 should always be absolute when scripts are invoked through &quot;#!&quot;.\n        test &quot;`ls -l -d &quot;${path}&quot; 2&gt; /dev/null | wc -l`&quot; -eq 1 || exit 1\n        # Change to the folder containing the file to resolve relative links.\n        folder=`expr &quot;${path}&quot; : &quot;\\(.*/\\)[^/][^/]*/*$&quot;` || exit 1\n        path=`expr &quot;x\\`ls -l -d &quot;${path}&quot;\\`&quot; : &quot;[^&gt;]* -&gt; \\(.*\\)&quot;`\n        cd &quot;${folder}&quot;\n        # If the last path was not a link then we are in the target folder.\n        test -n &quot;${path}&quot; || pwd\n    done\n)\n</code></pre>\n'}, {'answer_id': 35374073, 'author': 'Simon Rigét', 'author_id': 3546836, 'author_profile': 'https://Stackoverflow.com/users/3546836', 'pm_score': 7, 'selected': False, 'text': "<p>This should do it:</p>\n<pre><code>DIR=&quot;$(dirname &quot;$(realpath &quot;$0&quot;)&quot;)&quot;\n</code></pre>\n<p>This works with symlinks and spaces in path.</p>\n<p>Please see the man pages for <code>dirname</code> and <code>realpath</code>.</p>\n<p>Please add a comment on how to support MacOS. I'm sorry I can verify it.</p>\n"}, {'answer_id': 35514432, 'author': 'James Ko', 'author_id': 4077294, 'author_profile': 'https://Stackoverflow.com/users/4077294', 'pm_score': 4, 'selected': False, 'text': '<p>Here is the simple, correct way:</p>\n\n<pre><code>actual_path=$(readlink -f "${BASH_SOURCE[0]}")\nscript_dir=$(dirname "$actual_path")\n</code></pre>\n\n<p>Explanation:</p>\n\n<ul>\n<li><p><strong><code>${BASH_SOURCE[0]}</code></strong> - the full path to the script. The value of this will be correct even when the script is being sourced, e.g. <code>source &lt;(echo \'echo $0\')</code> prints <strong>bash</strong>, while replacing it with <code>${BASH_SOURCE[0]}</code> will print the full path of the script. (Of course, this assumes you\'re OK taking a dependency on Bash.)</p></li>\n<li><p><strong><code>readlink -f</code></strong> - Recursively resolves any symlinks in the specified path. This is a GNU extension, and not available on (for example) BSD systems. If you\'re running a Mac, you can use Homebrew to install GNU <code>coreutils</code> and supplant this with <strong><code>greadlink -f</code></strong>.</p></li>\n<li><p>And of course <strong><code>dirname</code></strong> gets the parent directory of the path.</p></li>\n</ul>\n'}, {'answer_id': 36322330, 'author': 'Jay jargot', 'author_id': 6010343, 'author_profile': 'https://Stackoverflow.com/users/6010343', 'pm_score': -1, 'selected': False, 'text': '<p>Look at the test at bottom with weird directory names. </p>\n\n<p>To change the working directory to the one where the Bash script is located, you should try this simple, <strong>tested</strong> and verified with <strong>shellcheck</strong> solution:</p>\n\n<pre><code>#!/bin/bash --\ncd "$(dirname "${0}")"/. || exit 2\n</code></pre>\n\n<p>The test:</p>\n\n<pre><code>$ ls \napplication\n$ mkdir "$(printf "\\1\\2\\3\\4\\5\\6\\7\\10\\11\\12\\13\\14\\15\\16\\17\\20\\21\\22\\23\\24\\25\\26\\27\\30\\31\\32\\33\\34\\35\\36\\37\\40\\41\\42\\43\\44\\45\\46\\47testdir" "")"\n$ mv application *testdir\n$ ln -s *testdir "$(printf "\\1\\2\\3\\4\\5\\6\\7\\10\\11\\12\\13\\14\\15\\16\\17\\20\\21\\22\\23\\24\\25\\26\\27\\30\\31\\32\\33\\34\\35\\36\\37\\40\\41\\42\\43\\44\\45\\46\\47symlink" "")"\n$ ls -lb\ntotal 4\nlrwxrwxrwx 1 jay stacko   46 Mar 30 20:44 \\001\\002\\003\\004\\005\\006\\a\\b\\t\\n\\v\\f\\r\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\ !"#$%&amp;\'symlink -&gt; \\001\\002\\003\\004\\005\\006\\a\\b\\t\\n\\v\\f\\r\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\ !"#$%&amp;\'testdir\ndrwxr-xr-x 2 jay stacko 4096 Mar 30 20:44 \\001\\002\\003\\004\\005\\006\\a\\b\\t\\n\\v\\f\\r\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\\ !"#$%&amp;\'testdir\n$ *testdir/application &amp;&amp; printf "SUCCESS\\n" ""\nSUCCESS\n$ *symlink/application &amp;&amp; printf "SUCCESS\\n" ""\nSUCCESS\n</code></pre>\n'}, {'answer_id': 40217561, 'author': 'Nam G VU', 'author_id': 248616, 'author_profile': 'https://Stackoverflow.com/users/248616', 'pm_score': -1, 'selected': False, 'text': '<p>Based on <a href="https://stackoverflow.com/questions/59895/can-a-bash-script-tell-which-directory-it-is-stored-in/246128#246128">this answer</a>, I suggest the clarified version that gets <code>SCRIPT_HOME</code> as the containing folder of any currently-running Bash script:</p>\n<pre><code>s=${BASH_SOURCE[0]} ; s=`dirname $s` ; SCRIPT_HOME=`cd $s ; pwd`\necho $SCRIPT_HOME\n</code></pre>\n'}, {'answer_id': 42025938, 'author': 'ankostis', 'author_id': 548792, 'author_profile': 'https://Stackoverflow.com/users/548792', 'pm_score': -1, 'selected': False, 'text': '<p>This <em>one-liner</em> works on <a href="https://en.wikipedia.org/wiki/Cygwin" rel="nofollow noreferrer">Cygwin</a> even if the script has been called from <em>Windows</em> with <code>bash -c &lt;script&gt;</code>:</p>\n<pre><code>set mydir=&quot;$(cygpath &quot;$(dirname &quot;$0&quot;)&quot;)&quot;\n</code></pre>\n'}, {'answer_id': 42038422, 'author': 'puchu', 'author_id': 404949, 'author_profile': 'https://Stackoverflow.com/users/404949', 'pm_score': 2, 'selected': False, 'text': '<p><code>$0</code> is not a reliable way to get the current script path. For example, this is my <code>.xprofile</code>:</p>\n<pre><code>#!/bin/bash\necho &quot;$0 $1 $2&quot;\necho &quot;${BASH_SOURCE[0]}&quot;\n# $dir/my_script.sh &amp;\n</code></pre>\n<blockquote>\n<p>cd /tmp &amp;&amp; ~/.xprofile &amp;&amp; source ~/.xprofile</p>\n</blockquote>\n<pre><code>/home/puchuu/.xprofile\n/home/puchuu/.xprofile\n-bash\n/home/puchuu/.xprofile\n</code></pre>\n<p>So please use <code>BASH_SOURCE</code> instead.</p>\n'}, {'answer_id': 43333425, 'author': 'BuvinJ', 'author_id': 3220983, 'author_profile': 'https://Stackoverflow.com/users/3220983', 'pm_score': 3, 'selected': False, 'text': '<p>This worked for me when the other answers here did not:</p>\n\n<pre><code>thisScriptPath=`realpath $0`\nthisDirPath=`dirname $thisScriptPath`\necho $thisDirPath\n</code></pre>\n'}, {'answer_id': 49194320, 'author': 'User8461', 'author_id': 8594421, 'author_profile': 'https://Stackoverflow.com/users/8594421', 'pm_score': 4, 'selected': False, 'text': '<p>These are short ways to get script information:</p>\n\n<p>Folders and files:</p>\n\n<pre><code>    Script: "/tmp/src dir/test.sh"\n    Calling folder: "/tmp/src dir/other"\n</code></pre>\n\n<p>Using these commands:</p>\n\n<pre><code>    echo Script-Dir : `dirname "$(realpath $0)"`\n    echo Script-Dir : $( cd ${0%/*} &amp;&amp; pwd -P )\n    echo Script-Dir : $(dirname "$(readlink -f "$0")")\n    echo\n    echo Script-Name : `basename "$(realpath $0)"`\n    echo Script-Name : `basename $0`\n    echo\n    echo Script-Dir-Relative : `dirname "$BASH_SOURCE"`\n    echo Script-Dir-Relative : `dirname $0`\n    echo\n    echo Calling-Dir : `pwd`\n</code></pre>\n\n<p>And I got this output:</p>\n\n<pre><code>     Script-Dir : /tmp/src dir\n     Script-Dir : /tmp/src dir\n     Script-Dir : /tmp/src dir\n\n     Script-Name : test.sh\n     Script-Name : test.sh\n\n     Script-Dir-Relative : ..\n     Script-Dir-Relative : ..\n\n     Calling-Dir : /tmp/src dir/other\n</code></pre>\n\n<p>Also see: <a href="https://pastebin.com/J8KjxrPF" rel="noreferrer">https://pastebin.com/J8KjxrPF</a></p>\n'}, {'answer_id': 49867891, 'author': 'Rawstring', 'author_id': 2693082, 'author_profile': 'https://Stackoverflow.com/users/2693082', 'pm_score': 2, 'selected': False, 'text': '<p>This is how I work it on my scripts:</p>\n<pre><code>pathvar=&quot;$( cd &quot;$( dirname $0 )&quot; &amp;&amp; pwd )&quot;\n</code></pre>\n<p>This will tell you which directory the Launcher (current script) is being executed from.</p>\n'}, {'answer_id': 50635459, 'author': 'Alexander Mills', 'author_id': 1223975, 'author_profile': 'https://Stackoverflow.com/users/1223975', 'pm_score': 2, 'selected': False, 'text': '<p><em>If your Bash script is a symlink</em>, then this is the way to do it:</p>\n<pre><code>#!/usr/bin/env bash\n\ndirn=&quot;$(dirname &quot;$0&quot;)&quot;\nrl=&quot;$(readlink &quot;$0&quot;)&quot;;\nexec_dir=&quot;$(dirname $(dirname &quot;$rl&quot;))&quot;;\nmy_path=&quot;$dirn/$exec_dir&quot;;\nX=&quot;$(cd $(dirname ${my_path}) &amp;&amp; pwd)/$(basename ${my_path})&quot;\n</code></pre>\n<p>X is the directory that contains your Bash script (the original file, not the symlink). I swear to God this works, and it is the only way I know of doing this properly.</p>\n'}, {'answer_id': 53183593, 'author': 'Thamme Gowda', 'author_id': 1506477, 'author_profile': 'https://Stackoverflow.com/users/1506477', 'pm_score': 7, 'selected': False, 'text': '<p>Here is an easy-to-remember script:</p>\n<pre><code>DIR=&quot;$( dirname -- &quot;${BASH_SOURCE[0]}&quot;; )&quot;;   # Get the directory name\nDIR=&quot;$( realpath -e -- &quot;$DIR&quot;; )&quot;;    # Resolve its full path if need be\n</code></pre>\n'}, {'answer_id': 54133107, 'author': 'danemacmillan', 'author_id': 2973534, 'author_profile': 'https://Stackoverflow.com/users/2973534', 'pm_score': -1, 'selected': False, 'text': '<p>The <a href="https://stackoverflow.com/questions/59895/how-can-i-get-the-source-directory-of-a-bash-script-from-within-the-script-itsel/246128#246128">chosen answer</a> works very well. I\'m posting my solution for anyone looking for shorter alternatives that still addresses sourcing, executing, full paths, relative paths, and symlinks. Finally, this will work on <a href="https://en.wikipedia.org/wiki/MacOS" rel="nofollow noreferrer">macOS</a>, given that it cannot be assumed that GNU\'s coreutils\' version of <a href="https://linux.die.net/man/1/readlink" rel="nofollow noreferrer">readlink</a> is available.</p>\n<p>The gotcha is that it\'s not using Bash, but it is easy to use in a Bash script. While the OP did not place any constraints on the language of the solution, it\'s probably best that most have stayed within the Bash world. This is just an alternative, and possibly an unpopular one.</p>\n<p>PHP is available on macOS by default, and installed on a number of other platforms, though not necessarily by default. I realize this is a shortcoming, but I\'ll leave this here for any people coming from search engines, anyway.</p>\n<pre class="lang-bash prettyprint-override"><code>export SOURCE_DIRECTORY=&quot;$(php -r \'echo dirname(realpath($argv[1]));\' -- &quot;${BASH_SOURCE[0]}&quot;)&quot;\n</code></pre>\n'}, {'answer_id': 55352142, 'author': 'Top-Master', 'author_id': 8740349, 'author_profile': 'https://Stackoverflow.com/users/8740349', 'pm_score': 0, 'selected': False, 'text': '<p>The below stores the script\'s directory path in the <code>dir</code> variable.</p>\n<p>(It also tries to support being executed under <a href="https://en.wikipedia.org/wiki/Cygwin" rel="nofollow noreferrer">Cygwin</a> in Windows.)</p>\n<p>And at last it runs the <code>my-sample-app</code> executable with all arguments passed to this script using <code>&quot;$@&quot;</code>:</p>\n<pre class="lang-sh prettyprint-override"><code>#!/usr/bin/env sh\n\ndir=$(cd &quot;${0%[/\\\\]*}&quot; &gt; /dev/null &amp;&amp; pwd)\n\nif [ -d /proc/cygdrive ]; then\n    case &quot;$(uname -s)&quot; in\n        CYGWIN*|MINGW32*|MSYS*|MINGW*)\n            # We are under Windows, so translate path to Windows format.\n            dir=$(cygpath -m &quot;$dir&quot;);\n            ;;\n    esac\nfi\n\n# Runs the executable which is beside this script\n&quot;${dir}/my-sample-app&quot; &quot;$@&quot;\n</code></pre>\n'}, {'answer_id': 56031051, 'author': 'Andry', 'author_id': 2672125, 'author_profile': 'https://Stackoverflow.com/users/2672125', 'pm_score': -1, 'selected': False, 'text': '<p>There is no 100% portable and reliable way to request a path to a current script directory. Especially between different backends like <a href="https://en.wikipedia.org/wiki/Cygwin" rel="nofollow noreferrer">Cygwin</a>, <a href="https://en.wikipedia.org/wiki/MinGW" rel="nofollow noreferrer">MinGW</a>, <a href="https://en.wikipedia.org/wiki/MinGW#History" rel="nofollow noreferrer">MSYS</a>, Linux, etc. This issue was not properly and completely resolved in Bash for ages.</p>\n<p>For example, this could not be resolved if you want to request the path after the <code>source</code> command to make nested inclusion of another Bash script which is in turn use the same <code>source</code> command to include another Bash script and so on.</p>\n<p>In case of the <a href="https://linux.die.net/man/1/source" rel="nofollow noreferrer"><code>source</code></a> command, I suggest to replace the <code>source</code> command with something like this:</p>\n<pre><code>function include()\n{\n  if [[ -n &quot;$CURRENT_SCRIPT_DIR&quot; ]]; then\n    local dir_path=... get directory from `CURRENT_SCRIPT_DIR/$1`, depends if $1 is absolute path or relative ...\n    local include_file_path=...\n  else\n    local dir_path=... request the directory from the &quot;$1&quot; argument using one of answered here methods...\n    local include_file_path=...\n  fi\n  ... push $CURRENT_SCRIPT_DIR in to stack ...\n  export CURRENT_SCRIPT_DIR=... export current script directory using $dir_path ...\n  source &quot;$include_file_path&quot;\n  ... pop $CURRENT_SCRIPT_DIR from stack ...\n}\n</code></pre>\n<p>From now on, the use of <code>include(...)</code> is based on previous <code>CURRENT_SCRIPT_DIR</code> in your script.</p>\n<p>This only works when you can replace all <code>source</code> commands by <code>include</code> command. If you can\'t, then you have no choice. At least until developers of the Bash interpreter make an explicit command to request the current running script directory path.</p>\n<p>My own closest implementation to this:\n<a href="https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/bash/tacklelib/bash_tacklelib" rel="nofollow noreferrer">https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/bash/tacklelib/bash_tacklelib</a><br />\n<a href="https://github.com/andry81/tacklelib/tree/trunk/bash/tacklelib/bash_tacklelib" rel="nofollow noreferrer">https://github.com/andry81/tacklelib/tree/trunk/bash/tacklelib/bash_tacklelib</a></p>\n<p>(search for the <code>tkl_include</code> function)</p>\n'}, {'answer_id': 56186126, 'author': 'cdonat', 'author_id': 5053331, 'author_profile': 'https://Stackoverflow.com/users/5053331', 'pm_score': 2, 'selected': False, 'text': '<p>I usually use:</p>\n<pre><code>dirname $(which $BASH_SOURCE)\n</code></pre>\n'}, {'answer_id': 56264110, 'author': 'Chaim Leib Halbert', 'author_id': 1795125, 'author_profile': 'https://Stackoverflow.com/users/1795125', 'pm_score': 2, 'selected': False, 'text': '<p>Here\'s a command that works under either Bash or zsh, and whether executed stand-alone or sourced:</p>\n<pre><code>[ -n &quot;$ZSH_VERSION&quot; ] &amp;&amp; this_dir=$(dirname &quot;${(%):-%x}&quot;) \\\n    || this_dir=$(dirname &quot;${BASH_SOURCE[0]:-$0}&quot;)\n</code></pre>\n<h1>How it works</h1>\n<h2>The zsh current file expansion: <code>${(%):-%x}</code></h2>\n<p><code>${(%):-%x}</code> in zsh expands to the path of the currently-executing file.</p>\n<h3>The fallback substitution operator <code>:-</code></h3>\n<p>You know already that <code>${...}</code> substitutes variables inside of strings. You might not know that certain operations are possible (in both <a href="http://tldp.org/LDP/abs/html/parameter-substitution.html" rel="nofollow noreferrer">Bash</a> and <a href="http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion" rel="nofollow noreferrer">zsh</a>) on the variables during substitution, like the fallback expansion operator <code>:-</code>:</p>\n<pre><code>% x=ok\n% echo &quot;${x}&quot;\nok\n\n% echo &quot;${x:-fallback}&quot;\nok\n\n% x=\n% echo &quot;${x:-fallback}&quot;\nfallback\n\n% y=yvalue\n% echo &quot;${x:-$y}&quot;\nyvalue\n</code></pre>\n<h3>The <code>%x</code> prompt escape code</h3>\n<p>Next, we\'ll introduce prompt escape codes, a zsh-only feature. In zsh, <code>%x</code> will expand to the path of the file, but normally this is only when doing expansion for <a href="http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html#Shell-state" rel="nofollow noreferrer">prompt strings</a>. To enable those codes in our substitution, we can add a <code>(%)</code> flag before the variable name:</p>\n<pre><code>% cat apath/test.sh\nfpath=%x\necho &quot;${(%)fpath}&quot;\n\n% source apath/test.sh\napath/test.sh\n\n% cd apath\n% source test.sh\ntest.sh\n</code></pre>\n<h3>An unlikely match: the percent escape and the fallback</h3>\n<p>What we have so far works, but it would be tidier to avoid creating the extra <code>fpath</code> variable. Instead of putting <code>%x</code> in <code>fpath</code>, we can use <code>:-</code> and put <code>%x</code> in the fallback string:</p>\n<pre><code>% cat test.sh\necho &quot;${(%):-%x}&quot;\n\n% source test.sh\ntest.sh\n</code></pre>\n<p>Note that we normally would put a variable name between <code>(%)</code> and <code>:-</code>, but we left it blank. The variable with a blank name can\'t be declared or set, so the fallback is always triggered.</p>\n<h3>Finishing up: what about <code>print -P %x</code>?</h3>\n<p>Now we almost have the directory of our script. We could have used <code>print -P %x</code> to get the same file path with fewer hacks, but in our case, where we need to pass it as an argument to <code>dirname</code>, that would have required the overhead of a starting a new subshell:</p>\n<pre><code>% cat apath/test.sh\ndirname &quot;$(print -P %x)&quot;  # $(...) runs a command in a new process\ndirname &quot;${(%):-%x}&quot;\n\n% source apath/test.sh\napath\napath\n</code></pre>\n<p>It turns out that the hacky way is both more performant and succinct.</p>\n'}, {'answer_id': 56694491, 'author': 'Atul', 'author_id': 2881112, 'author_profile': 'https://Stackoverflow.com/users/2881112', 'pm_score': 5, 'selected': False, 'text': '<p>The shortest and most elegant way to do this is:</p>\n\n<pre class="lang-sh prettyprint-override"><code>#!/bin/bash\nDIRECTORY=$(cd `dirname $0` &amp;&amp; pwd)\necho $DIRECTORY\n</code></pre>\n\n<p>This would work on all platforms and is super clean.</p>\n\n<p>More details can be found in "<a href="https://www.electrictoolbox.com/bash-script-directory/" rel="noreferrer">Which directory is that bash script in?</a>". </p>\n'}, {'answer_id': 57505372, 'author': 'bestOfSong', 'author_id': 5010054, 'author_profile': 'https://Stackoverflow.com/users/5010054', 'pm_score': -1, 'selected': False, 'text': '<p>I want to comment on the previous answer up there (<em><a href="https://stackoverflow.com/questions/59895/how-can-i-get-the-source-directory-of-a-bash-script-from-within-the-script-itsel/201915#201915">How can I get the source directory of a Bash script from within the script itself?</a></em>), but don\'t have enough reputation to do that.</p>\n<p>I found a solution for this two years ago on Apple\'s documentation site: <a href="https://developer.apple.com/library/archive/documentation/OpenSource/Conceptual/ShellScripting/AdvancedTechniques/AdvancedTechniques.html" rel="nofollow noreferrer">https://developer.apple.com/library/archive/documentation/OpenSource/Conceptual/ShellScripting/AdvancedTechniques/AdvancedTechniques.html</a>. And I stuck to this method afterwards. It cannot handle soft link, but otherwise works pretty well for me. I\'m posting it here for any who needs it and as a request for comment.</p>\n<pre><code>#!/bin/sh\n\n# Get an absolute path for the poem.txt file.\nPOEM=&quot;$PWD/../poem.txt&quot;\n\n# Get an absolute path for the script file.\nSCRIPT=&quot;$(which $0)&quot;\nif [ &quot;x$(echo $SCRIPT | grep \'^\\/\')&quot; = &quot;x&quot; ] ; then\n    SCRIPT=&quot;$PWD/$SCRIPT&quot;\nfi\n</code></pre>\n<p>As shown by the code, after you get the absolute path of the script, then you can use the <a href="https://linux.die.net/man/1/dirname" rel="nofollow noreferrer"><code>dirname</code></a> command to get the path of the directory.</p>\n'}, {'answer_id': 57660444, 'author': 'LozanoMatheus', 'author_id': 2868547, 'author_profile': 'https://Stackoverflow.com/users/2868547', 'pm_score': 3, 'selected': False, 'text': '<p>You can do that just combining the script name (<code>$0</code>) with <a href="https://linux.die.net/man/1/realpath" rel="nofollow noreferrer"><code>realpath</code></a> and/or <a href="https://linux.die.net/man/1/dirname" rel="nofollow noreferrer"><code>dirname</code></a>. It works for Bash and Shell.</p>\n<pre class="lang-sh prettyprint-override"><code>#!/usr/bin/env bash\n\nRELATIVE_PATH=&quot;${0}&quot;\nRELATIVE_DIR_PATH=&quot;$(dirname &quot;${0}&quot;)&quot;\nFULL_DIR_PATH=&quot;$(realpath &quot;${0}&quot; | xargs dirname)&quot;\nFULL_PATH=&quot;$(realpath &quot;${0}&quot;)&quot;\n\necho &quot;RELATIVE_PATH-&gt;${RELATIVE_PATH}&lt;-&quot;\necho &quot;RELATIVE_DIR_PATH-&gt;${RELATIVE_DIR_PATH}&lt;-&quot;\necho &quot;FULL_DIR_PATH-&gt;${FULL_DIR_PATH}&lt;-&quot;\necho &quot;FULL_PATH-&gt;${FULL_PATH}&lt;-&quot;\n</code></pre>\n<p>The output will be something like this:</p>\n<pre><code># RELATIVE_PATH-&gt;./bin/startup.sh&lt;-\n# RELATIVE_DIR_PATH-&gt;./bin&lt;-\n# FULL_DIR_PATH-&gt;/opt/my_app/bin&lt;-\n# FULL_PATH-&gt;/opt/my_app/bin/startup.sh&lt;-\n</code></pre>\n<blockquote>\n<p>$0 is the name of the script itself</p>\n</blockquote>\n<p><em><a href="https://www.tldp.org/LDP/abs/html/othertypesv.html" rel="nofollow noreferrer">4.4. Special Variable Types</a></em></p>\n<p>An example: <em><a href="https://gist.github.com/LozanoMatheus/da96b4e44b89b13ad4af10ac4602ad99" rel="nofollow noreferrer">LozanoMatheus/get_script_paths.sh</a></em></p>\n'}, {'answer_id': 57666344, 'author': 'MatteoBee', 'author_id': 11004601, 'author_profile': 'https://Stackoverflow.com/users/11004601', 'pm_score': -1, 'selected': False, 'text': "<p>This is what I crafted throughout the years to use as a header on my Bash scripts:</p>\n<pre><code>## BASE BRAIN - Get where you're from and who you are.\nMYPID=$$\nORIGINAL_DIR=&quot;$(pwd)&quot; # This is not a hot air balloon ride..\nfa=&quot;$0&quot; # First Assumption\nta= # Temporary Assumption\nwa= # Weighed Assumption\nwhile true; do\n    [ &quot;${fa:0:1}&quot; = &quot;/&quot; ] &amp;&amp; wa=$0 &amp;&amp; break\n    [ &quot;${fa:0:2}&quot; = &quot;./&quot; ] &amp;&amp; ta=&quot;${ORIGINAL_DIR}/${fa:2}&quot; &amp;&amp; [ -e &quot;$ta&quot; ] &amp;&amp; wa=&quot;$ta&quot; &amp;&amp; break\n    ta=&quot;${ORIGINAL_DIR}/${fa}&quot; &amp;&amp; [ -e &quot;$ta&quot; ] &amp;&amp; wa=&quot;$ta&quot; &amp;&amp; break\ndone\nSW=&quot;$wa&quot;\nSWDIR=&quot;$(dirname &quot;$wa&quot;)&quot;\nSWBIN=&quot;$(basename &quot;$wa&quot;)&quot;\nunset ta fa wa\n( [ ! -e &quot;$SWDIR/$SWBIN&quot; ] || [ -z &quot;$SW&quot; ] ) &amp;&amp; echo &quot;I could not find my way around :( possible bug in the TOP script&quot; &amp;&amp; exit 1\n</code></pre>\n<p>At this point, your variables SW, SWDIR, and SWBIN contain what you need.</p>\n"}, {'answer_id': 58286511, 'author': 'Brad Parks', 'author_id': 26510, 'author_profile': 'https://Stackoverflow.com/users/26510', 'pm_score': 2, 'selected': False, 'text': '<h3>The following will return the current directory of the script</h3>\n\n<ul>\n<li>works if it\'s sourced, or not sourced</li>\n<li>works if run in the current directory, or some other directory.</li>\n<li>works if relative directories are used.</li>\n<li>works with bash, not sure of other shells.</li>\n</ul>\n\n<pre><code>/tmp/a/b/c $ . ./test.sh\n/tmp/a/b/c\n\n/tmp/a/b/c $ . /tmp/a/b/c/test.sh\n/tmp/a/b/c\n\n/tmp/a/b/c $ ./test.sh\n/tmp/a/b/c\n\n/tmp/a/b/c $ /tmp/a/b/c/test.sh\n/tmp/a/b/c\n\n/tmp/a/b/c $ cd\n\n~ $ . /tmp/a/b/c/test.sh\n/tmp/a/b/c\n\n~ $ . ../../tmp/a/b/c/test.sh\n/tmp/a/b/c\n\n~ $ /tmp/a/b/c/test.sh\n/tmp/a/b/c\n\n~ $ ../../tmp/a/b/c/test.sh\n/tmp/a/b/c\n</code></pre>\n\n<h3>test.sh</h3>\n\n<pre><code>#!/usr/bin/env bash\n\n# snagged from: https://stackoverflow.com/a/51264222/26510\nfunction toAbsPath {\n    local target\n    target="$1"\n\n    if [ "$target" == "." ]; then\n        echo "$(pwd)"\n    elif [ "$target" == ".." ]; then\n        echo "$(dirname "$(pwd)")"\n    else\n        echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"\n    fi\n}\n\nfunction getScriptDir(){\n  local SOURCED\n  local RESULT\n  (return 0 2&gt;/dev/null) &amp;&amp; SOURCED=1 || SOURCED=0\n\n  if [ "$SOURCED" == "1" ]\n  then\n    RESULT=$(dirname "$1")\n  else\n    RESULT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &gt;/dev/null 2&gt;&amp;1 &amp;&amp; pwd )"\n  fi\n  toAbsPath "$RESULT"\n}\n\nSCRIPT_DIR=$(getScriptDir "$0")\necho "$SCRIPT_DIR"\n</code></pre>\n'}, {'answer_id': 58562442, 'author': 'Alexander Stohr', 'author_id': 3423146, 'author_profile': 'https://Stackoverflow.com/users/3423146', 'pm_score': 3, 'selected': False, 'text': '<p>The top response does not work in all cases...</p>\n<p>As I had problems with the BASH_SOURCE with the included \'cd\' approach on some very fresh and also on less fresh installed <a href="https://en.wikipedia.org/wiki/Ubuntu_version_history#Ubuntu_16.04_LTS_.28Xenial_Xerus.29" rel="nofollow noreferrer">Ubuntu\xa016.04</a> (Xenial Xerus) systems when invoking the shell script by means of &quot;sh my_script.sh&quot;, I tried out something different that as of now seems to run quite smoothly for my purposes. The approach is a bit more compact in the script and is further much lesser cryptic feeling.</p>\n<p>This alternate approach uses the external applications \'<a href="https://linux.die.net/man/1/realpath" rel="nofollow noreferrer">realpath</a>\' and \'<a href="https://linux.die.net/man/1/dirname" rel="nofollow noreferrer">dirname</a>\' from the coreutils package. (Okay, not anyone likes the overhead of invoking secondary processes - but when seeing the multi-line scripting for resolving the true object it won\'t be that bad either having it solve in a single binary usage.)</p>\n<p>So let’s see one example of those alternate solution for the described task of querying the true absolute path to a certain file:</p>\n<pre><code>PATH_TO_SCRIPT=`realpath -s $0`\nPATH_TO_SCRIPT_DIR=`dirname $PATH_TO_SCRIPT`\n</code></pre>\n<p>But preferably you should use this evolved version to also support the use of paths with spaces (or maybe even some other special characters):</p>\n<pre><code>PATH_TO_SCRIPT=`realpath -s &quot;$0&quot;`\nPATH_TO_SCRIPT_DIR=`dirname &quot;$PATH_TO_SCRIPT&quot;`\n</code></pre>\n<p>Indeed, if you don’t need the value of the SCRIPT variable then you might be able to merge this two-liner into even a single line. But why really shall you spend the effort for this?</p>\n'}, {'answer_id': 59485855, 'author': 'Domi', 'author_id': 2228771, 'author_profile': 'https://Stackoverflow.com/users/2228771', 'pm_score': 2, 'selected': False, 'text': '<p>Python was mentioned a few times. Here is the JavaScript (i.e., <a href="https://en.wikipedia.org/wiki/Node.js" rel="nofollow noreferrer">Node.js</a>) alternative:</p>\n<pre class="lang-sh prettyprint-override"><code>baseDirRelative=$(dirname &quot;$0&quot;)\nbaseDir=$(node -e &quot;console.log(require(\'path\').resolve(\'$baseDirRelative\'))&quot;) # Get absolute path using Node.js\n\necho $baseDir\n</code></pre>\n'}, {'answer_id': 60157372, 'author': 'Gabriel Staples', 'author_id': 4561887, 'author_profile': 'https://Stackoverflow.com/users/4561887', 'pm_score': 4, 'selected': False, 'text': '<h2>Summary:</h2>\n<pre class="lang-sh prettyprint-override"><code>FULL_PATH_TO_SCRIPT=&quot;$(realpath &quot;${BASH_SOURCE[-1]}&quot;)&quot;\n\n# OR, if you do NOT need it to work for **sourced** scripts too:\n# FULL_PATH_TO_SCRIPT=&quot;$(realpath &quot;$0&quot;)&quot;\n\n# OR, depending on which path you want, in case of nested `source` calls\n# FULL_PATH_TO_SCRIPT=&quot;$(realpath &quot;${BASH_SOURCE[0]}&quot;)&quot;\n\n# OR, add `-s` to NOT expand symlinks in the path:\n# FULL_PATH_TO_SCRIPT=&quot;$(realpath -s &quot;${BASH_SOURCE[-1]}&quot;)&quot;\n\nSCRIPT_DIRECTORY=&quot;$(dirname &quot;$FULL_PATH_TO_SCRIPT&quot;)&quot;\nSCRIPT_FILENAME=&quot;$(basename &quot;$FULL_PATH_TO_SCRIPT&quot;)&quot;\n</code></pre>\n<h2>Details:</h2>\n<h2>How to obtain the <em>full file path</em>, <em>full directory</em>, and <em>base filename</em> of any script being <em>run</em> OR <em>sourced</em>...</h2>\n<p>...even when the called script is called from within another bash function or script, or when nested sourcing is being used!</p>\n<p>For many cases, all you need to acquire is the full path to the script you just called. This can be easily accomplished using <code>realpath</code>. Note that <code>realpath</code> is part of <strong>GNU coreutils</strong>. If you don\'t have it already installed (it comes default on Ubuntu), you can install it with <code>sudo apt update &amp;&amp; sudo apt install coreutils</code>.</p>\n<p><strong>get_script_path.sh</strong> (for the latest version of this script, see <a href="https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/bash/get_script_path.sh" rel="noreferrer">get_script_path.sh</a> in my <a href="https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world" rel="noreferrer">eRCaGuy_hello_world</a> repo):</p>\n<pre class="lang-sh prettyprint-override"><code>#!/bin/bash\n\n# A. Obtain the full path, and expand (walk down) symbolic links\n# A.1. `&quot;$0&quot;` works only if the file is **run**, but NOT if it is **sourced**.\n# FULL_PATH_TO_SCRIPT=&quot;$(realpath &quot;$0&quot;)&quot;\n# A.2. `&quot;${BASH_SOURCE[-1]}&quot;` works whether the file is sourced OR run, and even\n# if the script is called from within another bash function!\n# NB: if `&quot;${BASH_SOURCE[-1]}&quot;` doesn\'t give you quite what you want, use\n# `&quot;${BASH_SOURCE[0]}&quot;` instead in order to get the first element from the array.\nFULL_PATH_TO_SCRIPT=&quot;$(realpath &quot;${BASH_SOURCE[-1]}&quot;)&quot;\n# B.1. `&quot;$0&quot;` works only if the file is **run**, but NOT if it is **sourced**.\n# FULL_PATH_TO_SCRIPT_KEEP_SYMLINKS=&quot;$(realpath -s &quot;$0&quot;)&quot;\n# B.2. `&quot;${BASH_SOURCE[-1]}&quot;` works whether the file is sourced OR run, and even\n# if the script is called from within another bash function!\n# NB: if `&quot;${BASH_SOURCE[-1]}&quot;` doesn\'t give you quite what you want, use\n# `&quot;${BASH_SOURCE[0]}&quot;` instead in order to get the first element from the array.\nFULL_PATH_TO_SCRIPT_KEEP_SYMLINKS=&quot;$(realpath -s &quot;${BASH_SOURCE[-1]}&quot;)&quot;\n\n# You can then also get the full path to the directory, and the base\n# filename, like this:\nSCRIPT_DIRECTORY=&quot;$(dirname &quot;$FULL_PATH_TO_SCRIPT&quot;)&quot;\nSCRIPT_FILENAME=&quot;$(basename &quot;$FULL_PATH_TO_SCRIPT&quot;)&quot;\n\n# Now print it all out\necho &quot;FULL_PATH_TO_SCRIPT = \\&quot;$FULL_PATH_TO_SCRIPT\\&quot;&quot;\necho &quot;SCRIPT_DIRECTORY    = \\&quot;$SCRIPT_DIRECTORY\\&quot;&quot;\necho &quot;SCRIPT_FILENAME     = \\&quot;$SCRIPT_FILENAME\\&quot;&quot;\n</code></pre>\n<p><strong>IMPORTANT note on <em>nested <code>source</code> calls</em>:</strong> if <code>&quot;${BASH_SOURCE[-1]}&quot;</code> above doesn\'t give you quite what you want, try using <code>&quot;${BASH_SOURCE[0]}&quot;</code> instead. The first (<code>0</code>) index gives you the first entry in the array, and the last (<code>-1</code>) index gives you the last last entry in the array. Depending on what it is you\'re after, you may actually want the first entry. I discovered this to be the case when I sourced <code>~/.bashrc</code> with <code>. ~/.bashrc</code>, which sourced <code>~/.bash_aliases</code> with <code>. ~/.bash_aliases</code>, and I wanted the <code>realpath</code> (with expanded symlinks) to the <code>~/.bash_aliases</code> file, NOT to the <code>~/.bashrc</code> file. Since these are <em>nested</em> <code>source</code> calls, using <code>&quot;${BASH_SOURCE[0]}&quot;</code> gave me what I wanted: the expanded path to <code>~/.bash_aliases</code>! Using <code>&quot;${BASH_SOURCE[-1]}&quot;</code>, however, gave me what I did <em>not</em> want: the expanded path to <code>~/.bashrc</code>.</p>\n<p><strong>Example command and output:</strong></p>\n<ol>\n<li><em>Running</em> the script:\n<pre class="lang-sh prettyprint-override"><code>~/GS/dev/eRCaGuy_hello_world/bash$ ./get_script_path.sh \nFULL_PATH_TO_SCRIPT = &quot;/home/gabriel/GS/dev/eRCaGuy_hello_world/bash/get_script_path.sh&quot;\nSCRIPT_DIRECTORY    = &quot;/home/gabriel/GS/dev/eRCaGuy_hello_world/bash&quot;\nSCRIPT_FILENAME     = &quot;get_script_path.sh&quot;\n</code></pre>\n</li>\n<li><em>Sourcing</em> the script with <code>. get_script_path.sh</code> or <code>source get_script_path.sh</code> (the result is the exact same as above because I used <code>&quot;${BASH_SOURCE[-1]}&quot;</code> in the script instead of <code>&quot;$0&quot;</code>):\n<pre class="lang-sh prettyprint-override"><code>~/GS/dev/eRCaGuy_hello_world/bash$ . get_script_path.sh \nFULL_PATH_TO_SCRIPT = &quot;/home/gabriel/GS/dev/eRCaGuy_hello_world/bash/get_script_path.sh&quot;\nSCRIPT_DIRECTORY    = &quot;/home/gabriel/GS/dev/eRCaGuy_hello_world/bash&quot;\nSCRIPT_FILENAME     = &quot;get_script_path.sh&quot;\n</code></pre>\n</li>\n</ol>\n<p>If you use <code>&quot;$0&quot;</code> in the script instead of <code>&quot;${BASH_SOURCE[-1]}&quot;</code>, you\'ll get the same output as above when <em>running</em> the script, but this <em>undesired</em> output instead when <em>sourcing</em> the script:</p>\n<pre class="lang-sh prettyprint-override"><code>~/GS/dev/eRCaGuy_hello_world/bash$ . get_script_path.sh \nFULL_PATH_TO_SCRIPT               = &quot;/bin/bash&quot;\nSCRIPT_DIRECTORY                  = &quot;/bin&quot;\nSCRIPT_FILENAME                   = &quot;bash&quot;\n</code></pre>\n<p>And, apparently if you use <code>&quot;$BASH_SOURCE&quot;</code> instead of <code>&quot;${BASH_SOURCE[-1]}&quot;</code>, it will <em>not</em> work if the script is called from within another bash function. So, using <code>&quot;${BASH_SOURCE[-1]}&quot;</code> is therefore the best way to do it, as it solves both of these problems! See the references below.</p>\n<p><strong>Difference between <code>realpath</code> and <code>realpath -s</code>:</strong></p>\n<p>Note that <code>realpath</code> also successfully walks down symbolic links to determine and point to their targets rather than pointing to the symbolic link. If you do NOT want this behavior (sometimes I don\'t), then add <code>-s</code> to the <code>realpath</code> command above, making that line look like this instead:</p>\n<pre class="lang-sh prettyprint-override"><code># Obtain the full path, but do NOT expand (walk down) symbolic links; in\n# other words: **keep** the symlinks as part of the path!\nFULL_PATH_TO_SCRIPT=&quot;$(realpath -s &quot;${BASH_SOURCE[-1]}&quot;)&quot;\n</code></pre>\n<p>This way, symbolic links are NOT expanded. Rather, they are left as-is, as symbolic links in the full path.</p>\n<p>The code above is now part of my <a href="https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world" rel="noreferrer">eRCaGuy_hello_world</a> repo in this file here: <a href="https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/bash/get_script_path.sh" rel="noreferrer">bash/get_script_path.sh</a>. Reference and run this file for full examples both with and withOUT symlinks in the paths. See the bottom of the file for example output in both cases.</p>\n<h2>References:</h2>\n<ol>\n<li><a href="https://stackoverflow.com/a/14892459/4561887">How to retrieve absolute path given relative</a></li>\n<li>taught me about the <code>BASH_SOURCE</code> variable: <a href="https://unix.stackexchange.com/a/4653/114401">Unix &amp; Linux: determining path to sourced shell script</a></li>\n<li>taught me that <code>BASH_SOURCE</code> is actually an array, and we want the last element from it for it to work as expected inside a function (hence why I used <code>&quot;${BASH_SOURCE[-1]}&quot;</code> in my code here): <a href="https://unix.stackexchange.com/a/153061/114401">Unix &amp; Linux: determining path to sourced shell script</a></li>\n<li><code>man bash</code> --&gt; search for <code>BASH_SOURCE</code>:\n<blockquote>\n<p><strong><code>BASH_SOURCE</code></strong></p>\n<p>An array variable whose members are the source filenames where the corresponding shell function names in the <code>FUNCNAME</code> array variable are defined. The shell function <code>${FUNCNAME[$i]}</code> is defined in the file <code>${BASH_SOURCE[$i]}</code> and called from <code>${BASH_SOURCE[$i+1]}</code>.</p>\n</blockquote>\n</li>\n</ol>\n<h2>See also:</h2>\n<ol>\n<li>[my answer] <a href="https://unix.stackexchange.com/a/692485/114401">Unix &amp; Linux: determining path to sourced shell script</a></li>\n</ol>\n'}, {'answer_id': 60381515, 'author': 'Muhammad Adeel', 'author_id': 2407041, 'author_profile': 'https://Stackoverflow.com/users/2407041', 'pm_score': -1, 'selected': False, 'text': '<p>Keep it simple.</p>\n\n<pre><code>#!/usr/bin/env bash\nsourceDir=`pwd`\necho $sourceDir\n</code></pre>\n'}, {'answer_id': 62396544, 'author': 'todd_dsm', 'author_id': 1778702, 'author_profile': 'https://Stackoverflow.com/users/1778702', 'pm_score': 0, 'selected': False, 'text': "<p>I think the simplest answer is a parameter expansion of the original variable:</p>\n<pre><code>#!/usr/bin/env bash\n\nDIR=&quot;$( cd &quot;$( dirname &quot;${BASH_SOURCE[0]}&quot; )&quot; &gt;/dev/null 2&gt;&amp;1 &amp;&amp; pwd )&quot;\necho &quot;opt1; original answer: $DIR&quot;\necho ''\n\necho &quot;opt2; simple answer  : ${BASH_SOURCE[0]%/*}&quot;\n</code></pre>\n<p>It should produce output like:</p>\n<pre><code>$ /var/tmp/test.sh\nopt1; original answer: /var/tmp\n\nopt2; simple answer  : /var/tmp\n</code></pre>\n<p>The variable/parameter expansion <code>${BASH_SOURCE[0]%/*}&quot;</code> seems much easier to maintain.</p>\n"}, {'answer_id': 65430829, 'author': 'Thomas Guyot-Sionnest', 'author_id': 969196, 'author_profile': 'https://Stackoverflow.com/users/969196', 'pm_score': 2, 'selected': False, 'text': '<p>One advantage of this method is that it doesn\'t involve anything outside Bash itself and does not fork any subshell neither.</p>\n<p>First, use pattern substitution to replace anything not starting with <code>/</code> (i.e., a relative path) with <code>$PWD/</code>. Since we use a substitution to <em>match the first character of <code>$0</code></em>, we also have to append it back (<code>${0:0:1}</code> in the substitution).</p>\n<p>Now we have a full path to the script; we can get the directory by removing the last <code>/</code> and anything the follows (i.e., the script name). That directory can then be used in <code>cd</code> or as a prefix to other paths relative to your script.</p>\n<pre class="lang-sh prettyprint-override"><code>#!/bin/bash\n\nBIN=${0/#[!\\/]/&quot;$PWD/${0:0:1}&quot;}\nDIR=${BIN%/*}\n\ncd &quot;$DIR&quot;\n</code></pre>\n<p>If your script may be sourced rather than executed, you can of course replace <code>$0</code> with <code>${BASH_SOURCE[0]}</code>, such as:</p>\n<pre class="lang-sh prettyprint-override"><code>BIN=${BASH_SOURCE[0]/#[!\\/]/&quot;$PWD/${BASH_SOURCE[0]:0:1}&quot;}\n</code></pre>\n<p>This will work for executable scripts too. It\'s longer, but more polyvalent.</p>\n'}, {'answer_id': 65802617, 'author': 'ghchoi', 'author_id': 4227175, 'author_profile': 'https://Stackoverflow.com/users/4227175', 'pm_score': 2, 'selected': False, 'text': '<p>I tried the followings with 3 different executions.</p>\n<h3><code>echo $(realpath $_)</code></h3>\n<pre><code>. application         # /correct/path/to/dir or /path/to/temporary_dir\nbash application      # /path/to/bash\n/PATH/TO/application  # /correct/path/to/dir\n</code></pre>\n<h3><code>echo $(realpath $(dirname $0))</code></h3>\n<pre><code>. application         # failed with `realpath: missing operand`\nbash application      # /correct/path/to/dir\n/PATH/TO/application  # /correct/path/to/dir\n</code></pre>\n<h3><code>echo $(realpath $BASH_SOURCE)</code></h3>\n<p><code>$BASH_SOURCE</code> is basically the same with <code>${BASH_SOURCE[0]}</code>.</p>\n<pre><code>. application         # /correct/path/to/dir\nbash application      # /correct/path/to/dir\n/PATH/TO/application  # /correct/path/to/dir\n</code></pre>\n<p>Only <code>$(realpath $BASH_SOURCE)</code> seems to be reliable.</p>\n'}, {'answer_id': 67105198, 'author': 'l0b0', 'author_id': 96588, 'author_profile': 'https://Stackoverflow.com/users/96588', 'pm_score': 3, 'selected': False, 'text': '<p>None of the current solutions work if there are any newlines at the end of the directory name - They will be stripped by the command substitution. To work around this you can append a non-newline character inside the command substitution and then strip just that character off:</p>\n<pre class="lang-sh prettyprint-override"><code>dir=&quot;$(cd &quot;$(dirname &quot;${BASH_SOURCE[0]}&quot;)&quot; &amp;&amp; pwd &amp;&amp; echo x)&quot;\ndir=&quot;${dir%x}&quot;\n</code></pre>\n<p>This protects against two very common situations: Accidents and sabotage. A script shouldn\'t fail in unpredictable ways just because someone, somewhere, did a <code>mkdir $\'\\n\'</code>.</p>\n'}, {'answer_id': 67149152, 'author': 'Binary Phile', 'author_id': 75182, 'author_profile': 'https://Stackoverflow.com/users/75182', 'pm_score': 2, 'selected': False, 'text': '<p>Most answers either don\'t handle files which are symlinked via a relative path, aren\'t one-liners or don\'t handle BSD (Mac).  A solution which does all three is:</p>\n<pre><code>HERE=$(cd &quot;$(dirname &quot;$BASH_SOURCE&quot;)&quot;; cd -P &quot;$(dirname &quot;$(readlink &quot;$BASH_SOURCE&quot; || echo .)&quot;)&quot;; pwd)\n</code></pre>\n<p>First, cd to bash\'s conception of the script\'s directory.  Then readlink the file to see if it is a symlink (relative or otherwise), and if so, cd to that directory.  If not, cd to the current directory (necessary to keep things a one-liner).  Then echo the current directory via <code>pwd</code>.</p>\n<p>You could add <code>--</code> to the arguments of cd and readlink to avoid issues of directories named like options, but I don\'t bother for most purposes.</p>\n<p>You can see the full explanation with illustrations here:</p>\n<p><a href="https://www.binaryphile.com/bash/2020/01/12/determining-the-location-of-your-script-in-bash.html" rel="nofollow noreferrer">https://www.binaryphile.com/bash/2020/01/12/determining-the-location-of-your-script-in-bash.html</a></p>\n'}, {'answer_id': 68056148, 'author': 'mrucci', 'author_id': 133106, 'author_profile': 'https://Stackoverflow.com/users/133106', 'pm_score': 3, 'selected': False, 'text': '<p>This is, annoyingly, the only one-liner I\'ve found that works on both Linux and macOS when the executable script is a symlink:</p>\n<pre><code>SCRIPT_DIR=$(python -c &quot;import os; print(os.path.dirname(os.path.realpath(\'${BASH_SOURCE[0]}\')))&quot;)\n</code></pre>\n<p>or, similarly, using python3 pathlib module:</p>\n<pre><code>SCRIPT_DIR=$(python3 -c &quot;from pathlib import Path; print(Path(\'${BASH_SOURCE[0]}\').resolve().parent)&quot;)\n</code></pre>\n<p>Tested on Linux and macOS and compared to other solutions in this gist: <a href="https://gist.github.com/ptc-mrucci/61772387878ed53a6c717d51a21d9371" rel="nofollow noreferrer">https://gist.github.com/ptc-mrucci/61772387878ed53a6c717d51a21d9371</a></p>\n'}, {'answer_id': 72077148, 'author': 'M Imam Pratama', 'author_id': 9157799, 'author_profile': 'https://Stackoverflow.com/users/9157799', 'pm_score': 0, 'selected': False, 'text': '<p>If <strong>not sourced</strong> by parent script and <strong>not symlinked</strong>, <code>$0</code> is enough:</p>\n<pre class="lang-sh prettyprint-override"><code>script_path=&quot;$0&quot;\n</code></pre>\n<p>If <strong>sourced</strong> by parent script and <strong>not symlinked</strong>, use <a href="https://stackoverflow.com/a/35006505/9157799"><code>$BASH_SOURCE</code> or <code>${BASH_SOURCE[0]}</code></a>:</p>\n<pre class="lang-sh prettyprint-override"><code>script_path=&quot;$BASH_SOURCE&quot;\n</code></pre>\n<p>If <strong>symlinked</strong>, use <code>$BASH_SOURCE</code> with <a href="https://unix.stackexchange.com/q/136494/307359"><code>realpath</code> or <code>readlink -f</code></a> to get the real file path:</p>\n<pre class="lang-sh prettyprint-override"><code>script_path=&quot;$(realpath &quot;$BASH_SOURCE&quot;)&quot;\n</code></pre>\n<p>In addition, <code>realpath</code> or <code>readlink -f</code> returns the <strong>absolute path</strong>.</p>\n<p>To get <strong>the directory</strong> of the script, use <code>dirname</code>:</p>\n<pre class="lang-sh prettyprint-override"><code>script_directory=&quot;$(dirname &quot;$script_path&quot;)&quot;\n</code></pre>\n<h4>Note</h4>\n<ul>\n<li>For MacOS, get an alternative of <code>realpath</code> or <code>readlink -f</code> <a href="https://stackoverflow.com/q/1055671/9157799">here</a> or <a href="https://stackoverflow.com/q/3572030/9157799">here</a>.</li>\n<li>To make the code compatible with shells other than Bash, use <a href="https://stackoverflow.com/a/66026711/9157799">the <code>${var-string}</code> parameter expansion</a>. Example: <a href="https://stackoverflow.com/a/54755784/9157799">Make it compatible with Zsh</a>.</li>\n</ul>\n'}, {'answer_id': 72195658, 'author': 'Alfred.37', 'author_id': 16931965, 'author_profile': 'https://Stackoverflow.com/users/16931965', 'pm_score': 0, 'selected': False, 'text': '<p>You can get the source directory of a Bash script from within the script itself on follow short way:</p>\n<pre><code>script_path=$(dirname &quot;$(readlink -f &quot;$0&quot;)&quot;)&quot;/&quot;\necho &quot;$script_path&quot;\n</code></pre>\n<p>Sample output:</p>\n<pre><code>/home/username/desktop/\n</code></pre>\n'}, {'answer_id': 74638215, 'author': 'digory doo', 'author_id': 1823332, 'author_profile': 'https://Stackoverflow.com/users/1823332', 'pm_score': 0, 'selected': False, 'text': '<p>Yet another variant:</p>\n<pre><code>SELF=$(SELF=$(dirname &quot;$0&quot;) &amp;&amp; bash -c &quot;cd \\&quot;$SELF\\&quot; &amp;&amp; pwd&quot;)\necho &quot;$SELF&quot;\n</code></pre>\n<p>This works on macOS as well, determines the canonical path, and does not change the current directory.</p>\n'}]
['https://Stackoverflow.com/questions/59895', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/2908/']