Operating System - Linux
1745793 Members
4094 Online
108722 Solutions
New Discussion юеВ

Re: basename $0 in function

 
SOLVED
Go to solution
Steve Givens
Occasional Advisor

Basename $0 in function

I'm hoping someone can explain why I'm getting a function name returned from basename instead of the file name on HP-UX. The same code returns the filename on AIX and Sun. Here is an excerpt from the code:

F_Set_base ()
{
...
_ProgName=`${BASENAME} ${0} | ${AWK} -F\. '{print$1}'`
echo ${_ProgName}
...
}

Main ()
{
F_Set_base
...
}

Main $*


I get a value of _ProgName=F_Set_base instead of the script name I am running on the command line.

Thanks in advance,

Steve
11 REPLIES 11
Sandman!
Honored Contributor

Re: Basename $0 in function

You have to get the invoking script name outside of any function call otherwise what HP-UX is doing is correct i.e. returning the called function name.
Sandman!
Honored Contributor

Re: Basename $0 in function

Ignore my last post. The problem arises most likely from the fact that you are using uppercase variable names for standard UNIX utils like "basename" and "awk" i.e.

change -> _ProgName=`${BASENAME} ${0} | ${AWK} -F\. '{print$1}'`

to -> _ProgName=`basename ${0} | awk -F\. '{print$1}'`

~cheers
James R. Ferguson
Acclaimed Contributor

Re: Basename $0 in function

Hi Steve:

Copying your script as poated but adding the first three lines works as expected. That is, the basename of the file being executed is returned.

#!/usr/bin/sh
BASENAME=basename
AWK=awk
F_Set_base ()
{
_ProgName=`${BASENAME} ${0} | ${AWK} -F\. '{print$1}'`
echo ${_ProgName}
}
Main ()
{
F_Set_base
}
Main $*

...This applies equally to HP-UX and AIX.

You might try running your full script with 'set -u' to expose unset parameters; and with 'set -x' to print the command execution sequences. You could do this as:

# sh -ux ./myscript

Regards!

...JRF...
Dennis Handly
Acclaimed Contributor

Re: basename $0 in function

As Steve says, it returns the function name in ksh and and as James says, in the POSIX shell, it returns the name of the script.

Note: Instead of invoking basename and awk, you can replace both by using shell pattern matching:
_ProgName=${0##*/}
_ProgName=${_ProgName%.*}

curt larson_1
Honored Contributor

Re: Basename $0 in function

in the ksh shell, when you specify a function name followed by its arguments, if any, these arguments become the positional parameters inside the function, but do not change the current positional parameters for the invoking script. The value of positional parameter 0 is set to the name of the function, only when the function has been defined with the function compound command. When a POSIX function is invoked, $0 is not changed.

posix functions are defined with the syntax name(){body;}

and the function compound command syntax is function name {body;}
Bob_Vance
Esteemed Contributor

Re: Basename $0 in function

You didn't say what version of HPUX and what shell you are using.

The behavior you describe is from the Korn shell on HPUX 11.11.

The documentation states, within a function,
Posix shell:
... The positional parameter 0 is unchanged.
Korn shell:
... The positional parameter 0 is set to the function name.

NOTE that this appears to be a HPUX implementation issue.
The links to
.. KornShell 88
and
.. KornShell 93
on David Korn's home page, *neither* specify that $0 is set to the function name !!



The Korn shell is
... /usr/bin/ksh
.
Note that
... /usr/bin/sh
is the Posix shell, *not* the Bourne shell, which is
... /usr/old/bin/sh
.

If you force Korn shell with

#!/usr/bin/ksh

as the first line, you get

_ProgName= F_Set_base
.


If you force Posix shell with

#!/usr/bin/sh

as the first line, you get

_ProgName= script_name
.

If you do not force a specific shell at line 1 of the script, then the shell used will be the one that you are running at the time, usually the one named in /etc/passwd as your login shell. On HPUX, the system by default will use /usr/bin/sh (or, for single-user mode, /sbin/sh, which is also a Posix shell), e.g., cron or system startup scripts.

bv
"The lyf so short, the craft so long to lerne." - Chaucer
Bill Hassell
Honored Contributor

Re: Basename $0 in function

This is one of those corner cases between POSIX style shells like posix-sh, ksh, bash, etc (script name versus function name). This can easily be avoided by defining the script's basename at the beginning of the script. Functions will then inherit the globally defined variable:

#!/usr/bin/ksh

...
export MYNAME=${0##*/}
...
function SomeTask
{
echo $MYNAME
}
...


Bill Hassell, sysadmin
Steve Givens
Occasional Advisor

Re: Basename $0 in function

First of all, my thanks to everyone who posted. Some good suggestions and things to look at.

I'm not sure why HP-UX 11.11 treats this differently than other O/S's (namely AIX and Solaris)? Although my testing on HP has so far shown no differences in my scripts between the Korn and Posix settings, I am leary of relying on the approach of just setting everything to Posix. I know this doesn't work on my tests on a Sun server (maybe /bin/sh is still Bourne shell)?

And if I understand Curt's comments, using a posix function should return the script name for $0. But isn't the code I posted at the beginning of this thread in Posix format?

James R. Ferguson
Acclaimed Contributor
Solution

Re: Basename $0 in function

Hi Steve:

I agree that:

#!/bin/sh
function WHOAMI
{
echo "I am $0"
}
WHOAMI
echo "I am $0"

...produces different results using HP-UX or a Linus 'bash' shell than does AIX. In HP-UX, '/usr/bin/sh' is the POSIX shell. For AIX '/usr/bin/sh' links to the Korn shell. Both, including 'bash' have Posix standards incorportated as you can see from purusing the respective manpages.

Given that their *are* subtle differences in various shells in edge cases exemplified by the script above, I prefer to use the technique Bill noted; viz. to capture the value of $0 at a shell's startup. Thus, to obtain the basename of the running code:

#!/usr/bin/sh
# typeset MYNAME=${0##*/}

...

Regards!

...JRF...