Search code examples
bashargs

Bash $0 does not match command used at terminal


In a bash script I've made I am attempting to print out some information to the user (in response to a particular error) suggesting that they add a switch to their command. I thought $0 always contains the text that the user typed as the command at the terminal, so my bash looked like this: echo "try '$0 -s $@' instead."

I've found that when I call that script from a relative path, such as ./script.sh, $0 is "./script.sh" as I expect. However, if script.sh is in my PATH and I call it with script.sh, $0 is not "script.sh". It ends up being the absolute path to the script file instead.

I could use basename $0 to correct the second case, but that would mess up the first. Is there a way to find out exactly what text the user typed for the command that started the script file?


Solution

  • No, you can not generally find out what the user typed.

    The user could have:

    • Typed a function or wrapper instead, which runs your and other commands, and which may not pass on parameters.
    • Typed something in a highly non-Bourne shell, like Shelly's run_ "./script" ["--foo"].
    • Clicked a desktop menu instead of typing something.
    • Executed the script from a non-repeatable stream in a Java snippet running on an Android TV.

    Canonical behavior is for the caller to set argv[0] to "a filename string that is associated with the process being started" (POSIX), whatever it takes that to mean, and for you to echo that back to them in sh-like usage descriptions.

    Unfortunately for scripts, the caller's argv[0] gets lost in the indirection to the shebang interpreter, which instead ends up setting $0 to the filename argument it's interpreting.

    It's still fine though. The important thing is for you to identify yourself with basename "$0" or "$0" and indicate why the parameters are wrong. It's the user's responsibility to incorporate the changes into their particular workflow.