Is it possible that a sourced shell script knows its location? I've read determining path to sourced shell script but the answers focus on bash
and tcsh
and fail if a POSIX shell is used. $0
is also not the solution and yields wrong results.
A solution doesn't need to be 100% reliable. It's unlikely that the path contains hard or symlinks.
# sourcing the script should yield the absolute path to the script
. somedir/thescript
# within “thescript”
-> /tmp/foo/bar/somedir
Some background: The script is part of an existing application containing dozens of binaries in a bin
directory in a known location (varies per architecture) relative to the sourced script. To use the application the user sources the script which prepends the bin
directory to the PATH
, so the application's binaries can be easily invoked in the current shell (whichever shell that might be).
Best Answer
The location of the sourced script is not available unless you are using a shell that offers extensions to the POSIX specification. You can test this with the following snippet:
where
included.sh
containsIn bash, the name of the sourced script is in
$BASH_SOURCE
. In zsh (in zsh compatibility mode, not in sh or ksh compatibility mode), it's in$0
(note that in a function,$0
is the function name instead). In pdksh and dash, it isn't available. In ksh93, this method doesn't reveal the solution, but the full path to the included script is available as${.sh.file}
.If requiring bash or ksh93 or zsh is good enough, you can use this snippet:
You can try to guess the location of the script by looking at what files the shell has open. Experimentally this seems to work with dash and pdksh but not with bash or ksh93 which at least for a short script have closed the script file by the time they get around to executing it.
The script may not be the file with the highest-numbered descriptor if the script is sourced inside a complex script that has been playing with redirections. You may want to loop through the open files. This is not guaranteed to work anyway. The only reliable way to locate a sourced script is to use bash, ksh93 or zsh.
If you can change the interface, then instead of sourcing your script, have your script print out a shell snippet to be passed to
eval
in the caller. This is what scripts to set environment variables typically do. It allows your script to be written independently of the vagaries of the caller's shell and shell configuration.In the caller:
eval "`/path/to/setenv`"