简体   繁体   中英

Difference in behaviour while Sourcing a Script and Executing it on a KornShell

The only difference in Sourcing a Script and Executing it, I was aware of, is in the later case, the parent environment remains unaffected.

Consider this sample Script:

SETUP_DIR=`dirname $0`
echo $SETUP_DIR
echo $0
echo $1

The above script simply fetches the directory name of the running script. While trying to source it, the above script fails with the following error

$ . test.sh foo
dirname: invalid option -- k
Try `dirname --help' for more information.

-ksh
foo

The reason what it seems to me is, when sourcing it, as the script runs in the parent environment shell, the shell name is passed as the first argument, in this case its -ksh .

and dirname -ksh fails because of an -k , which is an invalid option for dirname

Strangely, this problem is not there while running in sh or bash

$ sh
sh-3.2$ . test.sh foo
.
sh
foo
sh-3.2$ bash
bash-3.2$ . test.sh foo
.
bash
foo
bash-3.2$
  • So I was wondering, is it a known documented behavior in KornShell (ksh)? How to resolve this issue?
  • My second generic question is, why does dirname 'sh' returns the current directory .

In answer to your second question, from man dirname :

Print NAME with its trailing /component removed; if NAME contains no /'s, output '.' (meaning the current directory).

This is why you get . when you run dirname sh .

I am unable to reproduce your error in ksh .

So I was wondering, is it a known documented behavior in corn shell? How to resolve this issue?

When ksh is started as a login shell by /bin/login , its $0 will be prefixed with - , so $0 will be -ksh instead of just ksh or /bin/ksh . Login does this to indicate to the shell that it is being started as a login shell , as this typically affects profile loading.

The ksh manual documents its adherence to this convention:

If the shell is invoked by exec(2), and the first character of argument zero ($0) is -, then the shell is assumed to be a login shell and commands are read from [...]

The hyphen prefix doesn't show up for me with bash, I assume that bash is editing the command line to stop it from being visible in the process listing.

As a result, dirname $0 is dirname -ksh , and dirname tries to parse that as passing the k , s and h options

You can get around this by explicitly terminating options parsing by dirname with -- , ie

dirname -- "$0"

My second generic question is, why does dirname 'sh' returns the current directory .

dirname is trying to be helpful and return a usable path even when there is no directory part of the path you're giving it. Since your "$0" only has one part, it assumes it is relative to the current working directory, ie sh == ./sh , and returns the .

This is documented as per dogbane's answer

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM