2

From man bash :

If the -c option is present, then commands are read from
the first non-option argument command_string.  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.

I don't understand the purpose of the $0 assignment.

I was exploring ways to pass arguments to multiple commands with xargs. The following solution works just fine (inspired from here), but I fail to understand why an argument is needed at the end :

[ Edit : following chepner's answer, the argument doesn't need to be empty, it can be anything indeed, but it has to exist ].

$ cat test
abc
def
ghi

$ cat test | xargs -n 1 /bin/bash -c 'echo "1-$@"; echo "2-$@";' 'dummyArgument'
1-abc
2-abc
1-def
2-def
1-ghi
2-ghi

Obviously the 'dummyArgument' is necessary for bash -c to be able to interpret $@, (it can even be empty '') because without it I get the following result :

$ cat test | xargs -n 1 /bin/bash -c 'echo "1-$@"; echo "2-$@";'
1-
2-
1-
2-
1-
2-

But how does it work ? Why do I need that 'dummyArgument' ?

ChennyStar
  • 350
  • 1
  • 2
  • 11

2 Answers2

2

It doesn't have to be empty quotes (which is how you provide an empty string as a concrete value). It can be any value, if you don't actually care about the value of $0 in your command. If you do care, then you would provide the value you want instead of an empty string.

But whatever the first argument is, it will be used to set $0. There is no option to leave $0 unset and apply the arguments to $1 et al intead.

Other common "dummy" values are _, sh, and bash.

An easy way to see the difference between an empty argument and no argument is to use the set command, then look at the value of $#. First, no positional arguments:

$ set --
$ echo "$#"
0

Now, a single empty argument

$ set -- ''
$ echo "$#"
1
chepner
  • 497,756
  • 71
  • 530
  • 681
  • OK, I get this. Yes I tested, the argument doesn't have to be empty, it can be any string. But I still don't understand why `bash -c` needs an argument after the command string to be able to interpret `$@` – ChennyStar Jun 07 '21 at 13:46
  • I updated my question. Now that I know that the argument doesn't have to be empty, my real question in fact is : why do we need that `'dummyArgument'` ? – ChennyStar Jun 07 '21 at 13:59
  • 1
    Specifying the value of `$0` simply isn't optional. There isn't a separate option like `-0` to use if you decide provide a value; `$0`, `$1`, etc are simply set using the given positional parameters, in the order given. If you don't account for this, then what you *think* is the value to be used for `$1` will actually be assigned to `$0`, etc. – chepner Jun 07 '21 at 15:23
2

I don't understand the purpose of the $0 assignment.

Its purpose is to let you give your inline script a name, potentially for decorating diagnostic messages. There is nothing interesting about it.

$ cat foo.sh
echo my name is $0
$
$ bash foo.sh a b c
my name is foo.sh
$
$ bash -c 'echo my name is $0' foo a b c
my name is foo
oguz ismail
  • 1
  • 16
  • 47
  • 69
  • 2
    Yes I get it. `xargs` helps to distinguish the different arguments passed to `bash -c`. Anyway, if by chance somebody stumbles on this post with the same questions, comparing the output of the following commands will help to understand what's going on : `$ echo foo bar baz | xargs bash -c 'echo $0 - $@'` and `$ echo foo bar baz | xargs bash -c 'echo $0 - $@' 'dummy'`. Thanks again, you pointed me in the right direction – ChennyStar Jun 07 '21 at 15:58