Bash scripting 101: Chapter 3: For he'$ a jolly good fellow (loopy loops)
for: for NAME [in WORDS ... ;] do COMMANDS; done
The `for' loop executes a sequence of commands for each member in a
list of items. If `in WORDS ...;' is not present, then `in "$@"' is
assumed. For each element in WORDS, NAME is set to that element, and
the COMMANDS are executed.
is what the bash command help has to say about "for" ( help for ), not very informative is it?
rates somewhere in readability between INS and IRS i would guess (having only sampled one)
what does it mean for the shell scripter?
we'll start out simple:
#!/bin/bash
for I in 1 2 3 4 5 6 7 8 9
do
echo -e "printing number $I \n"
done
it will print out 1-9 with a small text message..ooh try it yaselves!
why does it do this? well line by line, blow by blow below
- #!/bin/bash
the ever famous SHEBANG line
- for I in 1 2 3 4 5 6 7 8 9
for each and everyone of the "list" (1 2 3 4 5 6 7 8 9) put them one by one into "I", do the thing stated between "do" and "done" and then put the next thing in the list into "I" and do it again.
- do
start the "for" "loop" block
- echo -e "printing number $I \n"
echo/print with backslash escaped interpretation "printing number $I \n" insert the content of variable I there. i also indented (increased spaces before it) this makes subroutines and loops easier to see, increase a few spaces for each "level" (you'll see this more and more further on).
- done
end the "for" "loop" block
so let's get creative with counting, can we do this with variables? but of course!
#!/bin/bash
ONE="1 2 3"
FOUR="4 5 6"
SEVEN="7 8 9"
for I in $ONE $FOUR $SEVEN
do
echo -e "printing $I \n"
done
you did what???
i did...
- #!/bin/bash
- ONE="1 2 3"
this one is new, i'm putting "1 2 3" into a variable called "ONE", i'm putting spaces between the number to make sure for will see them as separate numbers
- FOUR="4 5 6"
see point (2) different name and values, same deal
- SEVEN="7 8 9"
see point (2)
- for I in $ONE $FOUR $SEVEN
this one takes a little explaining, what bash first sees is:
for I in $ONE $FOUR $SEVEN
then it looks over it again, cause the variables need to be looked into and it sees:
for I in 1 2 3 $FOUR $SEVEN
for I in 1 2 3 4 5 6 $SEVEN
for I in 1 2 3 4 5 6 7 8 9
it actually does all the variables in one go(i think, bash programmers please inform me if i'm wrong), i've simply separated them to illustrate the process
- do
start the do/done part for loop (the looping part)
- echo -e "printing $I \n"
we know this one by now
- done
end the do/done part
isn't this a complex way when i can just write echo -e "1 2 3 4 5 6 7 8 9"? Yes, it is, it is an example, bear with me, and see the potential instead of my silly examples :-)
#!/bin/bash
ONE="1 2 3"
FOUR="4 5 6"
SEVEN="7 8 9"
TWELVE="$ONE $FOUR $SEVEN 10 11 12"
for I in $TWELVE
do
echo -e "printing $I \n"
done
here comes the break down. I'll skip all lines except for the ones i've actually added or made changes to :-)
- TWELVE="$ONE $FOUR $SEVEN 10 11 12"
the Variable "TWELVE" is the same as the content of variable ONE FOUR SEVEN 10 11 12
IE. TWELVE is "1 2 3 4 5 6 7 8 9 10 11 12" notice however how easily i could mix numbers and variables
- for I in $TWELVE
use the contents of variable TWELVE (see point 1) as a list of words/elements to put into I
dude didn't you say there was potential here?
yes i did and yes there is
as a person online i sometimes want to know if a host exists with a certain TLD (Top Level Domain(.com, .gov and so on))
i use a script like this:
#!/bin/bash
test "${1}" = "" && echo 'script needs at least a domain name without tld to check' && exit 1
TOPLEVELDOMAINS="edu com gov net org"
for TLD in $TOPLEVELDOMAINS
do
host $1.$TLD
done
you can from now on just assume i'll just "break down" the lines that contain new stuff
WHOOA!!! you are really trying to give me a headache right..admit it!!!
no i'm not, it's not as bad as it looks, i promise, it's actually so simple you'll probably go "aha" and give me a look of "wasn't there more to it than that?"
- test "${1}" = "" && echo 'script needs at least a domain name without tld to check' && exit 1
test is a bash-built-in command, it exits with (0) if the expression is "true" and with (1) if it's false
- here we are asking "test" to compare the strings "${1}" and "" (empty string),
- ${1} is a "referance" to "$1"
actually it's "entry one of "$@" and $@ is a special variable (array actually(more on that later)) containing all the commandline switches given when program is called (when you type the script name)ie $@ is "$1 $2 $3..." and what ${1} does is simply ask for the "$1" entry.
- since that first entry is (unless you gave a hostname) empty it'll match ""
- if it matches "" it(test) will exit with (0)
- if it exits with (0) it is "true" and means that && (AND) is done
if you remember chapter one we used "||" (OR) here is now the opposite "&&" (AND) "if the program before did OK then do THIS one too"
- echo '...' this one you know
- since echo will work almost guaranteed "&&"(AND) "exit (1)" will exit the script returning a (1) the "one" is a signal that means "i had an error, i'm exiting/stopping program".
This is done in case you call this shell script from another shellscript and that other shellscript checks if THIS one executed properly.
- TOPLEVELDOMAINS="edu com gov net org"
into variable TOPLEVELDOMAINS put the most common tld's
- for TLD in $TOPLEVELDOMAINS
for each value in TOPLEVELDOMAINS, put it into TLD and
- do
start the "do" block
- host $1.$TLD
host is a command that looks up ip numbers from hostnames, or vice versa, what bash sees is:
iteration 1 (first repeat)host name_you_entered_as_command_line_argument.edu
iteration 2 (second repeat)host name_you_entered_as_command_line_argument.com
iteration 3 (third repeat)host name_you_entered_as_command_line_argument.gov
iteration 4 (fourth repeat)host name_you_entered_as_command_line_argument.net
iteration 5 (fifth repeat)host name_you_entered_as_command_line_argument.org
so why didn't i put the "." in TOPLEVELDOMAINS as in ".com .edu..." i didn't since i'm lazy, it'd be 5 "." compared to one "." in the for/do/done block
- done
end do block
for you windows users out there, there is actually a way to do this too
ahhh but you see i want to look up some international tld's too!!! got ya now w0nderer don't i!!!
nope, you don't, read the next chapter :-)