for-loops

Moving onto the next line of code:

for arg; do
  ...
done

We saw a regular Bash for-loop earlier, in our experiment with delimiters and the IFS variable. This loop is a bit weird, though, because we don't see an arg variable explicitly defined by the code. Yet it's there, all the same.

If we haven't seen this variable defined yet, does that mean it's defined or built-in by the language? As usual, Googling turns up a StackOverflow post:

It's a special way of handling command-line options using for loop.

It's equivalent to:

for arg in "$@"; do
  ...

It's not specific to bash. It's defined in POSIX:

Scrolling down in the answer a bit, we see:

Omitting:

in word ...

shall be equivalent to:

in "$@"

The above statement implies that $@ expands to the list of arguments provided to the script. Let's see if that's true with another experiment.

Experiment- what does $@ evaluate to?

I write a new script (again named simply foo):

#!/usr/bin/env bash

echo "$@"

Running the script with some random arguments, we get:

$ ./foo bar baz buzz
bar baz buzz
$

Changing the script a bit:

#!/usr/bin/env bash

for arg in "$@";
do
  echo "$arg"
done

Running this, we get:

$ ./foo bar baz buzz
bar
baz
buzz
$

They print on separate lines this time, because now we're iterating over them with the for loop and making a separate call to echo for each arg, instead of printing them all at once via $@.

And finally, testing whether we can eliminate in $@:

#!/usr/bin/env bash

for arg;
do
  echo "$arg"
done

Running this results in:

$ ./foo bar baz buzz
bar
baz
buzz
$ 

Awesome! Nothing changed, meaning that the in $@ bit is optional in this case.

Wrapping Up

So from this line of code, we learned:

  • $@ stands for the arguments that you pass to the script
  • If you write a for loop but leave off the in ___ part, bash defaults to using $@

And summing up what we know up to this point:

  • we're iterating over each argument provided to our command...
  • ... but we only do that if that command is ruby.

Let's move on to the next line of code.