Ksh: How to get name of script when in same script

To get the script name the variable $0 can normally be used.
Problem happens when the command is started with a "dot space" as in: . myscript.sh .
$0 shows -ksh not myscript.sh
From within the script ps -f does not show myscript.sh either.
Someone suggested using readlink but cannot get that to work

Here is a test script:

#myscript.sh
echo myscript=$0
mypid=$$
echo mypid=$mypid
ps -f
ls /proc/$mypid/exe
readlink /proc/$mypid/exe
uname -a
Linux svappd02 2.6.32-754.11.1.el6.x86_64 #1 SMP Tue Jan 22 17:25:23 EST 2019 x86_64 x86_64 x86_64 GNU/Linux

Thanks!

The . command asks the shell to include the text found in the file named by its operand in the body of the currently running script and execute in the current shell execution environment without starting another shell or sub-shell to process the commands found in that file.

If it is important for the file you are running with the . command to accurately specify the name of the file from which . read those commands, the script calling it will need to cooperate with it something like:
Updated calling calling myscript.sh :

... ... ...
dotscript="my script.sh"
. "$dotscript"
... ... ...

Updated code in myscript.sh :

#myscript.sh
mypid=$$
echo "The code in $dotscript is being run by $0 with PID $mypid"

Ran new "myscript.sh" still shows "-ksh" not "myscript.sh"

$ . myscript.sh
The code in  is being run by -ksh with PID 1581

No. It is being run by -ksh as I explained in post #2. What it shows (by the two spaces between "in" and "is" in the output you showed us) is that you didn't set dotscript="myscript.sh" before running the command . myscript.sh as I suggested in post #2.

Don, I guess a better question is how to derive the script name when it's "sourced" WITHOUT hardwiring its name in the script itself.
I've been dealing with the fullpath to the script name using this paradigm in ksh:

#!/usr/bin/ksh
#set -x

thisFile="$(whence ${0})"
echo "this file->[${thisFile}]"

Obviously it doesn't work when the script is sourced.

I tried this for testing:

#!/usr/bin/ksh
set -x

echo "\$0 ->[${0}] \$# -> [${#}]"
#thisFile="$(whence ${0})"
if [[ "${0}" = -* ]]; then
   # cannot get this to work when sourced....
   thisFile="${1}"
else
   # bash-ism
   #thisFile="$(type -P ${0})"
   # ksh-ism
   thisFile="$(whence ${0})"
fi

echo "this file->[${thisFile}]"

how about this approach [covering bash/ksh - might need to enhance it for other (zsh/sh/etc)]

#!/bin/ksh
#set -x

#echo "\$0 ->[${0}] \$# -> [${#}] \$_ -> [${_}] "
case "${0}" in
   -bash) thisFile="${BASH_ARGV[0]}"
          ;;
   *ksh) thisFile="${_}"
          ;;
   *)
      #thisFile="$(type -P ${0})"
      thisFile="$(whence ${0})"
      ;;
esac

echo "this file->[${thisFile}]"
1 Like

Only bash provides a method:

echo "I am $BASH_SOURCE"

With ksh you have to stick to a workaround like Don's suggestion

dotscript="myscript.sh"; . "$dotscript"
echo "I am ${dotscript:-$0}"
1 Like

That is an interesting way to find what we're looking for in bash . Looking at the bash man page, it isn't obvious to me why it works.

Unfortunately, it doesn't really work for ksh . It works the second time if you try the commands:

. scriptname
. scriptname

because ksh sets the variable named _ to the last argument passed to the most recently completed synchronous command. I.e., after the first time you run . scriptname , ksh sets _ to scriptname so the second time you run . scriptname $_ (and ${_} ) expand to scriptname . But if you run the two commands:

echo "Hello World!"
. scriptname

When you're running the above script with ksh , the output from the dot command will be Hello World! , not scriptname .

Note also that having the #!/bin/ksh comment at the start of the script is misleading; the commands in this file will be run by whatever shell issued the command:

. scriptname

within the current shell execution environment at that time. Unlike, when you're executing a script directly (instead of dotting the script), the file named scriptname only has to be readable (it doesn't matter if it is executable).

2 Likes

Well, I did remember discussing something similar in the past - here's the relevant thread.

Here's the modified test harness:

#!/usr/bin/ksh
# path to the script - includes if the script has been SOURCED: ". ./scriptPath.sh"
#
#set -x

#echo "\$0 ->[${0}] \$# -> [${#}] \$.sh.file-> [${.sh.file}] "
#thisFile="$(whence ${0})"
case "${0}" in
   -bash) thisFile="${BASH_SOURCE}"
          ;;
   *ksh) thisFile="${.sh.file}"
          ;;
   *)
      #thisFile="$(type -P ${0})"
      thisFile="$(whence ${0})"
      ;;
esac

echo "this file->[${thisFile}]"

Now it works for both: bash and ksh - when sourced OR executed.
Don,
I left the shebang so that the script could be either sourced OR executed.

2 Likes

Thanks.

It still won't work with ksh88 , but that will work fine with ksh93 .

1 Like

vgersh99, that works! Thanks!