Basename $0 in function (719 Views)
Reply
Occasional Advisor
Steve Givens
Posts: 14
Registered: ‎05-18-2004
Message 1 of 12 (719 Views)
Accepted Solution

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
Honored Contributor
Sandman!
Posts: 2,220
Registered: ‎01-13-2005
Message 2 of 12 (719 Views)

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.
Honored Contributor
Sandman!
Posts: 2,220
Registered: ‎01-13-2005
Message 3 of 12 (719 Views)

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
Acclaimed Contributor
James R. Ferguson
Posts: 21,184
Registered: ‎07-06-2000
Message 4 of 12 (719 Views)

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...
Acclaimed Contributor
Dennis Handly
Posts: 25,071
Registered: ‎03-06-2006
Message 5 of 12 (719 Views)

Re: basename $0 in function

[ Edited ]

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%.*}

Honored Contributor
curt larson_1
Posts: 764
Registered: ‎08-23-2002
Message 6 of 12 (719 Views)

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;}
Esteemed Contributor
Bob_Vance
Posts: 602
Registered: ‎06-13-2000
Message 7 of 12 (719 Views)

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
Honored Contributor
Bill Hassell
Posts: 14,205
Registered: ‎05-29-2000
Message 8 of 12 (719 Views)

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
}
...
Occasional Advisor
Steve Givens
Posts: 14
Registered: ‎05-18-2004
Message 9 of 12 (719 Views)

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?

Acclaimed Contributor
James R. Ferguson
Posts: 21,184
Registered: ‎07-06-2000
Message 10 of 12 (719 Views)

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...

Occasional Advisor
Steve Givens
Posts: 14
Registered: ‎05-18-2004
Message 11 of 12 (719 Views)

Re: Basename $0 in function

What are the pattern matches described above "saying"?

_ProgName=${0##*/}
_ProgName=${_ProgName%.*}
Honored Contributor
Bill Hassell
Posts: 14,205
Registered: ‎05-29-2000
Message 12 of 12 (719 Views)

Re: Basename $0 in function

The constructs:

> _ProgName=${0##*/}
> _ProgName=${_ProgName%.*}

will return $0 (the script or function name depending on the shell you are using), strip all leading directories (ie, /usr/local/bin/myscript.sh becomes myscript.sh) and the second line takes myscript.sh and strips away any trailing .stuff such as .sh or .exe or whatever. Note that the last construct strips just the last .stuff, so a script named:

myscript.ver3.4.2a

will be truncated to myscript.ver.3.4

Note that Unix has no inherent concept of a type-extension so some script writers will use .ksh or .sh but others skip the extra characters.
The opinions expressed above are the personal opinions of the authors, not of HP. By using this site, you accept the Terms of Use and Rules of Participation.