Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a bash script file, which is put under some directory added to $PATH so that I can call the script from any directory.

There is another text file under the same directory as the script. I wonder how to refer to the text file in the script?

For example, if the script is just to output the content of the text file, cat textfile won't work, since when calling the script from a different directory, the text file is not found.

share|improve this question
A related issue recently came up here: Get path of current script when executed through a symlink – Caleb Aug 1 '11 at 10:28
This question answers how to get a bash script files path reliably, I added that to my path: stackoverflow.com/q/4774054/1695680 – ThorSummoner Jul 16 '15 at 22:18
up vote 12 down vote accepted

These should work the same, as long as there are no symlinks (in the path expansion or the script itself):

  • MYDIR="$(dirname "$(realpath "$0")")"

  • MYDIR="$(dirname "$(which "$0")")"

  • A two step version of any of the above:

    MYSELF="$(realpath "$0")"


If there is a symlink on the way to your script, then which will provide an answer not including resolution of that link. If realpath is not installed by default on your system, you can find it here.

[EDIT]: As it seems that realpath has no advantage over readlink -f suggested by Caleb, it is probably better to use the latter. My timing tests indicate it is actually faster.

share|improve this answer
@Caleb Oh yes, thanks for the escapes :) – rozcietrzewiacz Aug 1 '11 at 10:03
No problem. By the way where does realpath come from on your system. (For others that don't have it you can use readlink -f – Caleb Aug 1 '11 at 10:27
@Caleb Actually I thought it belonged to the set of standard GNU utilities (coreutils), but I can see now it is a separate package. – rozcietrzewiacz Aug 1 '11 at 10:48
@rozcietrzewiacz realpath dates back from before readlink -f (and even readlink, IIRC) was in GNU coreutils (there were several similar tools around. readlink -f eventually became the de facto standard); realpath is only kept for compatibility with scripts that still use it. – Gilles Aug 1 '11 at 21:38
@Gil I see. Thanks for enlightening :) – rozcietrzewiacz Aug 1 '11 at 21:40

My systems do not have realpath as suggested by rozcietrzewiacz.

You can accomplish this using the readlink command. The advantage of using this over parsing which or other solutions is that even if a part of the path or the filename executed was a symlink, you would be able to find the directory where the actual file was.

MYDIR="$(dirname "$(readlink -f "$0")")"

Your text file could then be read into a variable like this:

share|improve this answer
@rozcietrzewiacz: I actually wasn't refering to just your which suggestion. The normal solution for this involves either just dirname or a combination of cd and pwd in a subshell. Readlink has the advantage here. realpath seems to pretty much be just a wrapper for readlink -f anyway. – Caleb Aug 1 '11 at 11:07
I don't know how realpath is different from readlink -f. I can only see it gives me the same results (as opposed to which). – rozcietrzewiacz Aug 1 '11 at 11:21

$0 in the script will be the full path to the script, and dirname will take a full path and give you just the directory, so you can do this to cat textfile:

$ cat "$(dirname -- "$0")/textfile"
share|improve this answer
While this seems to work without realpath $0, you are wrong in saying that "$0 in the script will be the full path to the script". – rozcietrzewiacz Jul 31 '11 at 0:28
@roz In what way? – Michael Mrozek Jul 31 '11 at 0:38
$0 is the command as it was run, which can be e.g. ../script.sh. – rozcietrzewiacz Jul 31 '11 at 0:43
So, actually $(dirname "$0") returns the relative path to the script, as part of the invoked command - not the absolute path. This can lead to problems in scripts that change directories while running. – rozcietrzewiacz Jul 31 '11 at 1:03
@roz Ah, interesting. So I guess it wouldn't cause a problem here since he's calling something on the path by name, but it would break other things. Thanks – Michael Mrozek Jul 31 '11 at 1:09

You can put this at the top of your script:

cd "${BASH_SOURCE%/*}" || exit

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

Source: http://mywiki.wooledge.org/BashFAQ/028

share|improve this answer

Commandlinefu shows several different ways here.

share|improve this answer
You can provide off-site links, but always include at least a summary of the part that is a relevant answer to the question in your answer. – Caleb Aug 1 '11 at 9:47

I always use which to find the full path of an executable from the PATH. For instance:

which python

If you combine this with the dirname command then you get:

wp=`which python`
dn=`dirname $wp`
ls $dn
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.