如何使用bash / shell更改argv [0]值?

时间:2018-01-23 17:31:32

标签: bash shell sh

该脚本应该能够在shell / bash脚本中更改argv [0]值。 我在一篇较旧的帖子上找到了但却无法理解它在做什么。 有人可以解释这条线的工作原理:

sh -c ". '$0'" argv0new "$@"

test ".$INNERCALL"是否也是变量?

原始问题:How to change argv[0] value in shell / bash script?

#! /bin/bash    # 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 "$@"
    # bash -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

3 个答案:

答案 0 :(得分:2)

当取消设置变量INNERCALL时,脚本会使用一组特定参数调用自身。它设置变量以避免无限循环,然后以允许脚本设置自己的$0的方式调用自身。然后内部实例执行test之外的代码,这表明$0现在确实设置为脚本作者选择的特定值。完成后,我们返回脚本的外部实例,然后退出。

真正的好处是sh -c 'script...' arg0 arg1 arg2$0设置为脚本本身之后的第一个参数(在此示例中为arg0)。

答案 1 :(得分:0)

请注意,它不会更改argv0的​​值,但会使用argv0new创建新进程

改变

sh -c ". '$0'" argv0new "$@"

通过

exec sh -c ". '$0'" argv0new "$@"

也可以通过sh改变bash。

对于bash From bash Invoking-Bash

  

-c

     

从第一个非选项参数command_string中读取并执行命令,然后退出。如果在command_string之后存在参数,则将第一个参数分配给$ 0,并将任何剩余的参数分配给位置参数。赋值为$ 0设置shell的名称,用于警告和错误消息。

答案 2 :(得分:0)

让我们一行一行地了解

test ".$INNERCALL" = .YES

基本上这会看到$INNERCALL中是否已包含值YES。 Shell的""函数以安全的方式进行变量扩展,并将其全部编组为一个值,例如。

foo="hello"
bar=", world!"
echo "foobar is: $foo$bar"

打印foobar is: hello, world!

|| {
...
}

这使用||运算符来表示,如果先前的程序返回非零值(例如test是一个程序,如果关联的条件为false则返回1),然后执行此代码块,否则跳过它(有关||的更多信息,请参阅this link

export INNERCALL=YES

这会将INNERCALL设置为YES,这意味着这只会针对第一级执行

sh -c ". '$0'" argv0new "$@"
exit $?

这就是魔术发生的地方。 sh -c打开一个新shell,然后从后面的字符串中读取它的参数。 ". '$0'"在当前sh的值上使用$0的源函数,该值应该是当前文件。

基本上sh -c ". '$0'"只是在子sh进程中再次打开当前文件,然后该行的其余部分替换参数: argv0new成为新的$ 0,并通过包括"$@"

保留文件的原始参数

然后exit $?返回子进程运行的任何返回值。

其余代码只是为了证明除$0之外的所有参数都相同,并且$0已被替换。

tl; dr 它会打开一个子shell进程,告诉它读取当前文件,替换参数,然后导出一个测试值,使其不会无限循环。