如何在shell / bash脚本中更改argv [0]的值?

3
set命令可用于更改位置参数$1 $2 ...的值。但是,是否有任何方法可以更改$0?
(注:$0是指shell脚本文件名或者shell程序名称)

请参考UNIX stackexchange上的类似问题 - maxschlepzig
3个回答

2
在Bash 5及以上版本中,您可以像这样更改$0
$ cat bar.sh
#!/bin/bash
echo $0
BASH_ARGV0=lol
echo $0
$ ./bar.sh 
./bar.sh
lol

ZSH 甚至支持直接将值赋给 0
$ cat foo.zsh
#!/bin/zsh
echo $0
0=lol
echo $0
$ ./foo.zsh 
./foo.zsh
lol

1

这里介绍另一种方法。它是通过直接执行命令来实现的,比使用“点”命令(sourcing)要好一些。但是,这种方法只适用于shell解释器,而不是bash,因为sh支持同时传递-s -c选项:

#! /bin/sh
# try executing this script with several arguments to see the effect

test ".$INNERCALL" = .YES || {
    export INNERCALL=YES
    cat "$0" | /bin/sh -s -c : argv0new "$@"
    exit $?
}

printf "argv[0]=$0\n"
i=1 ; for arg in "$@" ; do printf "argv[$i]=$arg\n" ; i=`expr $i + 1` ; done

如果运行 ./the_example.sh 1 2 3,两个示例的预期输出应为:

argv[0]=argv0new
argv[1]=1
argv[2]=2
argv[3]=3

奇怪的是,如果你把所有的“/bin/sh”改成“/bin/bash”,它就不能工作了。这是在Ubuntu 16.04 LTS安装上发生的。不知何时,Linux神选择让/bin/sh成为一些“dash”东西,而不等于/bin/bash。所选答案https://dev59.com/_IHba4cB1Zd3GeqPMhWC#24581562没有这个问题。 - bgoodr
同意。如果我当时读清楚了那句话,"since sh supports" 应该让我理解 "shell interpreter" 在这个上下文中指的是 /bin/sh 解释器。 - bgoodr
1
@bgoodr :) 顺便问一下,为什么你不给答案点个赞呢?它对你有帮助吗? - sqr163
两个答案都很有帮助,所以我标记了它们。 - bgoodr

-2
#! /bin/sh
# try executing this script with several arguments to see the effect

test ".$INNERCALL" = .YES || {
    export INNERCALL=YES
    # this method works both for shell and bash interpreters
    sh -c ". '$0'" argv0new "$@"
    exit $?
}

printf "argv[0]=$0\n"
i=1 ; for arg in "$@" ; do printf "argv[$i]=$arg\n" ; i=`expr $i + 1` ; done

4
有几种方法可以改善这个答案。一些解释可能会有所帮助。您可以使用INNERCALL=YES exec sh -c ". '$0'" argv0new "$@"使内部调用代码更加简洁。我有点怀疑. '$0'命令存在被破坏的可能性,但我可以先不考虑那些需要非常不寻常的设置技巧。但如果没有解释,我就不能认为这是一个好的答案。 - Jonathan Leffler
@JonathanLeffler 任何软件只要能正常工作就是好的。源代码是最好的解释 ;) - sqr163
1
当然不是。请参考这个后续问题:https://stackoverflow.com/questions/48407615/how-to-change-argv0-value-using-bash-shell-explanation-required - tripleee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接