Is there a way for a sourced shell script to find out the path to itself? I'm mainly concerned with bash, though I have some coworkers who use tcsh.

I'm guessing I may not have a ton of luck here, since sourcing causes commands to be executed in the current shell, so $0 is still the current shell's invocation, not the sourced script. My best thought currently is to do source $script $script, so that the first positional parameter contains the necessary information. Anyone have a better way?

Wow, that's exactly what I was looking for, and I can barely find any reference to it in the documentation. Way to know your stuff.
–
JefromiDec 8 '10 at 19:42

I just had occasion to use this in tcsh, and noticed that it doesn't work without the shebang. Seems a bit odd for the behavior to change if you're just sourcing it, not executing it...
–
JefromiApr 20 '11 at 16:28

The tcsh version also doesn't seem to work if the script is sourced noninteractively (e.g. from a cshrc). I can't seem to find a way to get the information in that case. Any thoughts?
–
JefromiMay 9 '11 at 18:04

1

@clacke: I find that in all the versions of Bash that I tested from 2.05b to 4.2.37, including 4.1.9, that . and source worked identically in this regard. Note that $_ must be accessed in the first statement in the file, otherwise it will contain the last argument of the previous command. I like to include the shebang for my own reference so I know what shell it's supposed to be for and for the editor so it uses syntax highlighting.
–
Dennis WilliamsonMar 4 '13 at 11:51

1

Haha. Obviously I was testing by first doing source, then doing .. I apologize for being incompetent. They are indeed identical. Anyway, $BASH_SOURCE works.
–
clackeMar 5 '13 at 7:35

Thanks, a quick and helpful answer. Dennis wins the green check mark for giving a tcsh answer too. @Gilles: Right, I did find that in the documentation. Fortunately for my use case I almost certainly don't have to worry about it.
–
JefromiDec 8 '10 at 19:46

@CiroSantilli: Not always, read the Bash manual on the $_ special parameter: "At shell startup, set to the absolute pathname used to invoke the shell or shell script being executed as passed in the environment or argument list. Subsequently, expands to the last argument to the previous command, after expansion. Also set to the full pathname used to invoke each command executed and placed in the environment exported to that command. When checking mail, this parameter holds the name of the mail file."
–
Adam RosenfieldSep 17 '14 at 19:14

The reason the one-liner works is explained by the use of the BASH_SOURCE environment variable and its associate FUNCNAME.

BASH_SOURCE

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]}.

FUNCNAME

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 "main". This variable exists only when a shell function is executing. Assignments to FUNCNAME have no effect and return an error status. If FUNCNAME is unset, it loses its special properties, even if it is subsequently reset.

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.

Can't see why this was downvoted. The accepted answer doesn't let you find out what directory the script is in from within a function. But the proposed solution does. Knee-jerk downvotes don't help the community.
–
gkb0986Aug 31 '14 at 21:49

@mikeserv I wouldn't be so sure. The question says "I'm mainly concerned with bash, though I have some coworkers who use tcsh". It also includes the suggestive invocation source foo.bash. I've edited my answer to include at the top that this is a bash only solution.
–
gkb0986Aug 31 '14 at 22:00

You have to prepare to handle "." as the directory name under some common circumstances. I'd experiment a bit, as I remember the dirname built-in to ksh doing things a bit differently when "." appears in PATH.