How to change argv[0] value using bash/shell? [duplicate]

馋奶兔 提交于 2019-12-11 15:00:38

问题


The script should be able to change argv[0] value in shell / bash script. I found on an older post but couldn't really understand what it is doing. Could someone please explain how the line works:

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

Also is test ".$INNERCALL" meant to be a variable ?

Original question: 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

回答1:


Let's go through this line by line

test ".$INNERCALL" = .YES

basically this sees if $INNERCALL already has the value YES in it. Shell's "" function does variable expansion in a safe way, and marshalls it all into a value, e.g.

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

prints foobar is: hello, world!


|| {
...
}

This uses the || operator to say, if the previous program returned with a non-zero value (e.g. test is a program that returns 1 if the associated conditional is false), then execute this code block, otherwise skip it (see this link for more on ||)


export INNERCALL=YES

This sets INNERCALL to YES, which means that this only executes for the first level


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

This is where the magic happens. sh -c opens a new shell, which then reads its arguments from the string that follows. ". '$0'" uses sh's source function on the value currently at $0, which is supposed to be this current file.

Basically sh -c ". '$0'" just opens the current file again in a child sh process, then the rest of the line replaces the arguments: argv0new becomes the new $0, and you keep the original arguments to the file by also including "$@"

then exit $? returns whatever return value the child process runs.

the rest of the code is just to prove that all of the arguments except for $0 is the same, and $0 has been replaced.


tl;dr it opens up a child shell process, tells it to read the current file, replaces the arguments, and then exports a test value so that it doesn't infinite loop.




回答2:


The script calls itself with a particular set of parameters when the variable INNERCALL is unset. It sets the variable to avoid an infinite loop, then calls itself in a way which allows the script to set its own $0. The inner instance then executes the code outside of the test, which demonstrates that $0 is now indeed set to a particular value which the script's author chose. When this finishes, we return to the outer instance of the script, which then simply exits.

The real beef is that sh -c 'script...' arg0 arg1 arg2 sets $0 to the first argument after the script itself (arg0 in this example).




回答3:


note it doesn't change the value of argv0 but create a new process with argv0new

changing

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

by

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

would also work changing bash by sh.

For bash From bash Invoking-Bash

-c

Read and execute commands from the first non-option argument command_string, then exit. If there are arguments after the command_string, the first argument is assigned to $0 and any remaining arguments are assigned to the positional parameters. The assignment to $0 sets the name of the shell, which is used in warning and error messages.



来源:https://stackoverflow.com/questions/48407615/how-to-change-argv0-value-using-bash-shell

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!