I'm having some trouble sorting out the beginning of some fiction that I'm working on, so I figured I'd switch gears and write up a continuation of the bash script examples. This got too long, so I'm going to have to continue it yet again in the near future, but for now, have some more bash scripty goodness.
Continuing where Bash Script Examples left off...
Return Values
Every line that executes produces a return value. Generally the return value is a zero for success and a non-zero for failure. The return value of the previous command or function can be used to decide what action to take next. There are a few different ways to leverage this.
Note that I chose to use
rm
in many examples, when a file doesn't exist, it
will complain on standard error. I don't mention this in the command output
below, but many of the examples will also include the following:
rm: cannot remove 'file': No such file or directory
&& || if
To execute the next line only when the current line was successful, use &&
.
For example:
rm file && echo file removed
This will attempt to remove a file named file
from the current working directory and if it is successful it will then display file removed
.
Note that the && operator gives you multi-line commands for free, so that could also be expressed as this:
rm file &&
echo "File removed!"
To execute the next line only when the current line fails, use ||
.
For example:
rm file ||
echo "Failed to remove the file!"
Now, if removing the file fails it will print out Failed to remove the file!
These can be combined, but it can make it hard to read, for example:
rm file &&
echo "File removed!" ||
echo "Failed to remove file"
This will output File removed
if it succeeds in removing file
or it will print out Failed to remove file
if it fails.
The if statement can also be used for conditional execution. For example:
if rm file ; then
echo "File removed!"
else
echo "Failed to remove file"
fi
This will print out File removed!
if it succeeds in removing file
or it will print out Failed to remove file
.
The logic can be reversed by using the !
operator:
if ! rm file ; then
echo "Failed to remove file"
else
echo "File removed!"
fi
true
and false
and []
It occurs to me now that maybe I should have used the true
built-in instead of removing a file in those examples. Bash has a couple of special, boolean built-ins, namely true
and false
. These return 0 and 1 as their exit codes, respectively.
For example:
if true ; then
echo "True!"
fi
This will produce the output: True!
And of course there is false:
if ! false ; then
echo "False!"
fi
This will produce the output: False!
There are also string and number comparison operations that an be used in an
if
statement by using the square brackets []
.
For example:
if [ 0 -eq 0 ] ; then
echo "Zero equals Zero!"
fi
if [ 0 -lt 1 ] ; then
echo "Zero is less than one!"
fi
if [ 1 -gt 0 ] ; then
echo "One is greater than zero!"
fi
I=2
if [ ${I} -lt 100 ] ; then
echo "${I} is less than 100"
fi
if [ "one" = "one" ] ; then
echo "running out of contrived examples!"
fi
All of which will produce the following:
Zero equals Zero!
Zero is less than one!
One is greater than zero!
2 is less than 100
running out of contrived examples!
Return values from functions
When you wrap a bunch of commands in a function you probably want to pass the error state back to the main script. There are two ways to do this, one is with an explicit return statement.
For example:
# This function always returns one.
one(){
return 1
}
The other way is to use the error status of the last line to execute.
For example:
remove_it() {
rm file
}
if remove_it ; then
echo "File removed!"
else
echo "Failed to remove file"
fi
In this example, the last line of the function is the rm
command and it will set the return code even though there is no explicit return in the remove_it
function. Like the previous blocks, this will print out File removed!
if it succeeds in removing file
or it will print out Failed to remove file
.
Loops
Bash supports for
, while
, until
, and something called select
. But I'm skipping select
for now because I don't really feel like it's a loop, it's uncommon, and frankly I write many of these posts while I'm offline and I don't want to go get online just to look up a practical example. So, I'll save that for another time.
for
The for loop can loop over a number range or a set of arbitrary values.
for a range
First, the number range example:
for ((i=0;i<10;i++)) ; do
echo "i is ${i}"
done
This will start ${i}
at zero and execute the echo
command ten times, displaying the following:
i is 0
i is 1
i is 2
i is 3
i is 4
i is 5
i is 6
i is 7
i is 8
i is 9
for arbitrary values in a list
Now, a range of arbitrary values from a string literal:
for i in 1 2 3 steem ; do
echo "i is ${i}"
done
This will produce the following output:
i is 1
i is 2
i is 3
i is steem
for arbitrary globbing
A very common use of the for loop is to loop over file names in a directory using globbing. I'm not going to go into detail on globbing right now because that would take me on a lengthy detour from loops, but I'll probably cover the topic later. For now, globbing is taking some expression of tokens that have a special meaning and expanding them to match file names.
Here is a for loop that uses a very common directory glob:
for dir in */ ; do
echo "Dir: ${dir}"
done
Assuming there are sub-directories in the current directory, this would print their names.
For example, it may produce something like the following:
Dir: bin/
Dir: boot/
Dir: dev/
...
for array values
This is a take on the loop over arbitrary values where an array is used to supply the arbitrary values.
For example:
VALUES=("one" "more" "time")
for VALUE in ${VALUES[@]} ; do
echo "value: ${VALUE}"
done
Will produce the following output:
value: one
value: more
value: time
while
and until
The while
loop executes for as long as the exit status of the test expression is true. It sounds more complex than it is, it behaves like the if
statement but repeats its body. Even that sounds complicated, so here's a simple example:
For example:
while true ; do
echo "This is the song that never ends..."
done
This will loop forever, printing out This is the song that never ends...
The until
loop is like the while loop, but it runs until its expression evaluates to false. For example:
until false ; do
echo "This is the song that never ends..."
done
This will loop forever, printing out This is the song that never ends...
Summary
Now that I've said how simple it is I'm going to end these examples here so that when I come back to this thread I can post what looks like a horribly complicated while loop, but is really full of awesome.
Here's a summary of what's been covered so far:
- conditional execution of the next statement using
&&
and||
- if statements
- implicit and explicit function return values
- for loops over numbers
- for loops over lists
- for loops with globbing
- while loops
- until loops
Image source is Pixabay
After seeing a discussion in steemit.chat I wanted to go back through and add some sources to my old posts. Since this one is too old to edit, I'm leaving them here in a comment.
The man pages for Bash and all of the other commands I've used above appear to cover 100% the stuff that I put in. If you're not on a Linux or *nix system where you can view man pages, the Bash manual is available online.