How can I get the directory of my executing script?

hi,

I tried whence $0, but that just gives me the filename relative to where I am executing the script from. I need to get the full pathname.

thanks

pwd won't work?

regarding whence, I guess "$0" depends on how you execute the script ( via absolute path or relative path )

try executing your script with absolute path and check.

eg.

/this/is/my/abs/path/script.ksh

pwd gives the location of where I am executing the script from.

My users can execute it from anywhere, so I cant force them to put the absolute path

thanks

you can run from anywhere of course.
just use absolute path while executing.

what i mean to say is this

-bash-3.1$ pwd
/a/b
-bash-3.1$ /this/is/my/abs/path/script.ksh
-bash-3.1$ cd ..
-bash-3.1$ pwd
/a
-bash-3.1$ /this/is/my/abs/path/script.ksh

I am not sure if this solve your problem. just a try.

hi,

use : which <your script>

this assumes that PATH has been exported
cheers

which wont work, because there will be many scripts with the same name in different locations and they will be executed using many different ways.

Surely there must be a way to execute a script from any location and get that script to output it's full path to stdout??

At least in bash, $0 includes the relative or absolute path, depending on what the user typed. If it is a relative path (first character is not "/"), you just prepend $PWD/.

#!/bin/bash
if [ "#{0:0:1}" = "/" ]; then
    spath=$0
else
    spath=$PWD/$0
fi
echo "Script is at $spath"

I don't know ksh so I cannot help you with the exact syntax for that.

For a relative path, you'll end up with "/./" in the middle of the path. It's ugly but legal. You can get rid of that with a little more work.

Here is an old thread about this subject.

$PWD won;t work. That would give me the directory from where I am executing the script, not where the script is.

could you

ps -ef | grep my_script

from within your script?

Please read my response. If $0 contains a relative path, it is relative to $PWD!

For example, if the user's working directory is /home/foo and he runs the script (/home/bar/x) by typing "../bar/x" (which is what bash, at least, gives in $0), we combine $PWD and $0 to get "/home/foo/../bar/x" which is an absolute path to the script. Yes, the up and down with ".." is ugly, but it works.

The script supplied by DoxieLvr has some errors. Try...

#!/bin/bash
if [ "${0:0:1}" = "/" ]; then
    spath="$0"
else
    spath="$PWD/$0"
fi
spath=$(dirname "$spath")
echo "Script is at $spath"

For a script that can be executed by multiple users, I'm assuming that it exists in a directory that's contained within the PATH.

dirname `which script.ksh`

Hope this helps!

Post #6 indicates that 'which' can not be used. DoxieLvr's script with my corrections will provide the correct path to the script.

did you try what i have mentioned.

if I understood you correctly then that will work.

bash->cat a.sh 
#!/usr/bin/ksh
echo "this is where you executed the script from -- $(dirname $0)"
bash->pwd
/home-dev
bash->/home-dev/a.sh
this is where you executed the script from -- /home-dev
bash->mkdir test
bash->cp a.sh test
bash->/home-dev/test/a.sh
this is where you executed the script from -- /home-dev/test

is that what you want?

@JamesByars . What Operating System and shell are you running?

First inclination was mentioned in an earlier post. Works with POSIX shells.

whence $0

im working on Sun using ksh.

I can have 10 different copies of the same script in different locations. When the script executes, it needs to find it's location where it is.

Slight change.
Within "ksh" this should catch virtually every way of invoking the script (including ./scriptname and through $PATH ) and return an absolute path to the script.

whence -p "${0}"

However if the script is invoked with a path containing "." or ".." the result of the whence still contains those characters.

Finding a clean path to the script itself involves cleaning up the result of "whence".
One tortuous way is to:
1) Find the inode number of the script (extract from "ls -id").
2) User "dirname" to extract the path to the script,
"cd" to the directory containing the script,
and then store the result of "pwd -P".
The "-P" switch to "pwd" eliminates the effect of links.
The "pwd" also eliminates "." and ".." from the middle of the directory name.
3) Finally use "find" from the stored "pwd -P" with -xdev and -inum switches
to find the raw path to the script.

There has to be a better way!

Do you have PERL installed on your system? There are some functions that I have come across that can give you what you are looking for.

$ cat  /tmp/getpath.pl

#!/usr/bin/perl

use strict;
use warnings;

print GetAbsoluteFileName($0) . "\n";

exit 0;

sub GetAbsoluteFileName {
   my $passed_filename = shift;
   my $absolute_filename;
   use Cwd 'abs_path';

   #expand tildes
   $passed_filename =~ s{ ^ ~ ( [^/]* ) }
                 { $1
                       ? (getpwnam($1))[7]
                       : ( $ENV{HOME} || (getpwuid($<))[7]
                         )
   }ex;

   $absolute_filename = abs_path(ExpandEnvVars( $passed_filename ) );

   return $absolute_filename;
}

#Takes a string and substitutes the value of the environment variable and returns the string back
sub ExpandEnvVars {
    my $env_var = shift;

    # expand variables in $env_var, if environment var does not exist, leave it alone

    $env_var =~ s{
         \$                         # find a literal dollar sign
        (\w+)                       # find a "word" and store it in $1
    }{
        no strict 'refs';           # for $$1 below
        if (exists $ENV{$1}) {
            $ENV{$1};               # expand environment variables only
        } else {
            "\$$1";                 # environment var does not exist, so leave what they gave us
        }
    }egx;

   return $env_var;
}

$ /tmp/getpath.pl
/tmp/getpath.pl

$ ls -1 /tmp/test1/getpath.pl
/tmp/test1/getpath.pl

$ /tmp/test1/getpath.pl
/tmp/test1/getpath.pl

$ export MYTEST=/tmp/test2

$ ls -1 $MYTEST/getpath.pl
/tmp/test2/getpath.pl

$ $MYTEST/getpath.pl
/tmp/test2/getpath.pl

Think this should be marked [SOLVED]. The correct solutions are provided in BASH, KSH, and Perl.