在KornShell上获取脚本并执行脚本时的行为差异

时间:2012-12-17 09:59:38

标签: linux bash shell scripting ksh

我知道,采购脚本和执行脚本的唯一区别是,在后一种情况下,父环境不会受到影响。

请考虑以下示例脚本:

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

上述脚本只是获取正在运行的脚本的目录名称。在尝试获取它时,上面的脚本失败并出现以下错误

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

-ksh
foo

在我看来,原因在于,当脚本在父环境shell中运行时,shell名称作为第一个参数传递,在本例中为-ksh

dirname -ksh由于-k而失败,这是dirname的无效选项

奇怪的是,在sh或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$
  • 所以我想知道,这是KornShell(ksh)中已知的记录行为吗?如何解决这个问题?
  • 我的第二个通用问题是,为什么dirname 'sh'会返回当前目录.

2 个答案:

答案 0 :(得分:1)

回答第二个问题,来自man dirname

  

打印NAME,删除其尾随/组件;如果NAME包含否   /'s,输出'。' (意思是当前目录)。

这就是您在运行.时获得dirname sh的原因。

我无法在ksh中重现您的错误。

答案 1 :(得分:1)

  

所以我想知道,这是玉米壳中已知的记录行为吗?如何解决这个问题?

/bin/login将ksh作为登录shell启动时,其$0将以-为前缀,因此$0将为-ksh而不仅仅是ksh /bin/kshdirname $0Login does this to indicate to the shell that it is being started as a login shell,因为这通常会影响配置文件加载。

ksh手册记录了它遵守这一惯例:

  

如果shell由exec(2)调用,并且参数零($ 0)的第一个字符是 - ,则假定shell是登录shell并从[...]

使用bash不会出现连字符前缀,我假设bash正在编辑命令行以阻止它在进程列表中显示。

因此,dirname -kshk,dirname尝试将其解析为传递shdirname选项

您可以通过-- dirname -- "$0" 显式终止选项解析来解决这个问题,即

dirname
  

我的第二个通用问题是,为什么dirname'sh'会返回当前目录。

sh正试图提供帮助并返回一个可用的路径,即使您没有提供路径的目录部分也是如此。由于您的“$ 0”只有一个部分,因此它假设它相对于当前工作目录,即./sh == .,并返回{{1}}

根据dogbane的回答记录了这个