In ksh(1) and bash(1) it is possible to get arg0 of the command line using $0.
Sometimes you need to know the folder/directory from which the script was run. $0 can help us here. $0 will contain the command used to invoke the script, for example
/path/to/myscript.sh
./myscript.sh
relative/path/to/myscript.sh
../../somewhere/in/the/file/system/is/myscript.sh
However, non of these (bar the first example) can actually tell us the full path to the directory from which the script was executed. What we need to do is turn the relative paths into absolute ones.
To do this, first recognize that the at the beginning of execution of the script, the path to the script is relative to the current directory. Because of this we can cd(1) to the path part of $0 then use $PWD to obtain the full path of that directory. We need to do this in such a way that it does not disturb the current directory.
The following code does just this (place this code just after the #!/bin/bash
line):
SCRIPT_DIR=`( cd "${0%/*}" ; echo $PWD )`
What this does is it takes $0, removes everything after the last / and cd’s to that directory in a sub-shell, then outputs $PWD which is captured and stored in the variable SCRIPT_DIR.
A variation of this which will also work in sh(1)
_p=`dirname "$0"`; SCRIPT_DIR=`( cd "$_p" ; pwd )`; unset _p
UPDATE: Here is a much simpler way to achieve this:-
SCRIPT_DIR=$( cd $(dirname "$0") ; pwd )
Unless your script is being dotted in:
$ set -x
$ echo ‘echo dollar zero is $0’ > bar
+ echo echo dollar zero is $0
+ 1> bar
$ chmod +x bar
+ chmod +x bar
$ ./bar
+ ./bar
dollar zero is ./bar
$. ./bar
+ . ./bar
+ echo dollar zero is -ksh
dollar zero is -ksh
Use $_ instead:
$ cat bar
+ cat bar
echo dollar under is $_
echo dollar zero is $0
$ ./bar
+ ./bar
dollar under is ./bar
dollar zero is ./bar
$ . ./bar
+ . ./bar
+ echo dollar under is ./bar
dollar under is ./bar
+ echo dollar zero is -ksh
dollar zero is -ksh
$_ is the last word of the previous command. It just happens to be from the ksh command line when referenced before any other command.
$ cat foo
#!/bin/bash
echo $0
echo something else
echo $_
$ cat bar
#!/bin/bash
. ./foo
$ ksh foo
foo
something else
else
$ ksh bar
bar
something else
/bin/ksh
$_ is giving unpredictable results in this scenario, and $0 works in bash and ksh at least the versions on my machine (fc14)
$0 does not work if your script is sourced in. $_ will work IFF you capture it’s value in the very first statement in your script. I should have made that clear. It’s kind of like using $? – if your don’t capture it right after the statement your referencing, all bets are off.
Thank you Mathew ! I was testing this and all I got was a one (1) for a sourced in call. capturing it in the very first statement did the trick.
Ooops scratch that. Even when captured at the start of the script, $_ doesn’t work when the script is source-called with an option (it equals the option). e.g.,
. bar/foo
($_ will equal bar/foo)
. bar/foo gen
($_ will equal gen)
I tested $_ just on its own and it does appear to work (tested in bash and ksh on linux). I then did the same test for $0 again.
$ cat foo
#!/bin/ksh
echo $0
$ cat bar
#!/bin/ksh
. ./foo
$ ./foo
./foo
$ ./bar
./bar
If I replace #!/bin/ksh with #!/bin/bash I get the same result. $0 seems to be working fine.
Try
$ . ./foo
and
$ . ./bar
And after further experimentation this morning I discovered $_ is even trickier. Instead of doing
. ./some_profile
I did
X=./some_profile
. $X
and $_ in some_profile was ‘X’ not ‘some_profile’. It’s not perfect – you need to know what you’re doing to use it.
I just got your result where $_ is the previous command and not my file. This happens if the call to the containing script is in a script of commands itself. I have to withdraw $_ as a useful solution.