I have read that positional parameters start at $1
(for example: $1
, $2
, $3
and so on are positional parameters). But $0
is not a positional parameter.
But why $0
is not a positional parameter?
I think this could be a reason, but not sure:
Positional parameters only take their values when a script is executed. For example: if we do ./myScript Hello
, then $1
will have the value Hello
. But $0
can take its value on two occasions: when a script is executed (it would have the value of the script name), and when bash
itself is executed without a script (it would have the value bash
or -bash
).
Best Answer
@ikkachu has explained it better than I even could. I'll just add a history note.
The shell that came with the first versions of Unix (later named the Thompson shell) had no variable, but you could already write simple scripts that would take parameters.
$1
...$n
were already the arguments and$0
the name of the script (not the 1st argument) but were not called positional parameters then.Note that back then,
$1
was literally replaced with the first argument before shell interpretation.For instance, a script that had:
called as
would run
echo foo; echo bar
. That shell was a very simple one written for computers with few hundred kilobytes of memory.The Bourne shell came almost a decade later (in the late 70s) with a version of Unix that introduced the environment and other goodies.
The Bourne shell did come with variables and a lot more programming constructs.
The positional parameter terminology, at least when it comes to Unix shells, was introduced by the Bourne shell, and referred to the same thing,
$1
...$n
for the arguments of the script (and$0
still the script name). Like in the Thompson shell, you could only refer to the first 9 arguments ($1
to$9
) with positional parameters (but use shift or"$@"
orfor i do
loops to access the rest) (and that also explains (backward portability) why you need${10}
instead of$10
in most modernsh
implementations for the 10th ones).This time,
sh script 'foo; echo bar'
no longer causedecho bar
to be run, but still the Bourne shell introduced that infamous split+glob, I suppose not to break backward compatible too much with the Thompson shell so thatscript 'foo *'
wherescript
hasecho $1
still did callecho
withfoo
and the list of files in the current directory as arguments (like in the Thompson shell but this time through a different mechanism).scripts were also called shell procedures (note that the Bourne shell didn't have functions yet):
Functions were first introduced in the Korn shell (based on the Bourne shell) in the early 80s with a
syntax.
Functions were eventually added to the Bourne shell as well later in SysVR2 (1984) with a different syntax:
(but with unexpected behaviour when
any-command
was a simple command and had redirections which is probably the reason why POSIX only requires compound commands (like{ ...; }
the most often used one) be recognised there for the POSIXsh
).In both the Korn and Bourne shell,
$0
in the function was still the script's name, not the function name (while the$1
,$2
positional parameters refer to the function arguments).That changed in
ksh93
for thefunction f {
style of function definition where$0
becomes the function name in the function.In
zsh
,$0
is the function name like in ksh93.zsh
also introduced anonymous functions with either the:or
syntax, in which
$0
becomes(anon)
(or stays the script's name withset +o functionargzero
like when insh
/ksh
emulation).In
zsh
, like incsh
, the arguments of the scripts are also in the$argv
array, which lifts the confusion about the program name named similarly to the arguments.There, you can assign values to the position parameters with:
or
(and also
0=newprogramname
to change the program name).While in other Bourne-like shells, you need to use
set
to assign all at once:And you can't change
$0
.In
rc
(at least the Unix port), you can't do:But you can do:
to set the positional parameters. You can't change
$0
inrc
, but you can in its derivativees
with0=newprogramname
like inzsh
.TL;DR
The
$1
,$2
... to refer to the scripts arguments comes from the Thompson shell but were not called positional parameters yet. And$0
(probably chosen in reference toargv[0]
as @ikkachu well put it) refers to the script name.The positional parameters term comes from the Bourne shell.
$0
is not a positional parameter because it doesn't refer to an argument of the script. It refers to the script's name (or the shell'sargv[0]
when the shell doesn't execute any script).