Episode: 2649
Title: HPR2649: More ancillary Bash tips - 10
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2649/hpr2649.mp3
Transcribed: 2025-10-19 07:00:59

---

This is HPR Episode 2649, titled More Ancillary Mashedip, 10, and in part of the series Mashed
Cripting.
It is hosted by Dave Morris and in about 23 minutes long, and Karina next visit flag.
The summary is making decisions in Mashed Part 2.
This episode of HPR is brought to you by archive.org.
Universal access to all knowledge by heading over to archive.org forward slash donate.
Hello everybody, this is Dave Morris.
Welcome to Hacker Public Radio.
So I'm doing another show today about Bash Tips.
This is my 10th contribution to the Bash Cripting series, and we're talking here about making
decisions in Bash.
You can see all the other shows that relate to this one or proceed this one by looking
at the link section of the notes.
And there are long notes to go with the brief ones, the introductory ones.
Now last episode we looked at the tests that you need to use to make decisions in Bash.
In this episode we're going to use, we're going to look at some of the constructs, some
of the commands and types of commands that use these tests.
We're going to be looking at looping constructs, conditional constructs, and lists of commands,
and I'm going to refer to the GNU Bash Manual where necessary.
Now this show is the result of taking what I thought was going to be one reasonable length
show, turned out to be massive, and chopping it into two.
So I didn't re-record the audio, I just cut it into into two, changed the preamble.
So there are cases where the audio contains references to example files, which are called
Bash9EX2 or something like that.
The names have changed because this is shown on a 10 in this series.
I've updated the notes as necessary, but as I say I wasn't going to edit the audio
and replace the names of files and stuff like that because I'm sure you don't need me
to do that.
So let's get on with it.
So I'm going to whizz through some of the looping constructs that I mentioned earlier
on.
It's really to signal that they exist and give you a flavor of what they do.
There are equivalent sections in the GNU Bash Manual talking about looping constructs,
and there are more than the ones I'm going to look at here.
I'm just going to look at two called while and until because they contain the sort of
tests we've been looking at.
We'll leave four loops until another time.
I'll probably use them in examples without really explaining them, sorry about that.
So let's look at the while command.
Since x is the while command is while, followed by test commands, then on the next line do,
then followed by on a new line, commands that can be any number of commands one per line.
And the final bit of the construct is done.
The commands are executed as long as the test commands return an exit status, which is
zero.
In other words, the loop continues while the result is true.
That's why it's called while.
I won't say any more about that, hopefully that's pretty self-evident.
And there's other references, there's other places you can go for information.
There's an example coming in a minute anyway.
Next one is the until command.
This consists of until, followed by test commands, followed by on the next line do, followed
by a list of commands, followed by done on the next line.
These commands are executed as long as test commands returns an exit status, which is
non-zero.
So in other words, until it becomes true, loop until the result is true, which again
is why it's called until.
There's a couple of examples.
First one will print a variable i, increment it while its value is less than five.
So we'll output the number zero through four.
So we start with setting i to zero.
Then the while loop consists of a test, a while, followed by test, which is open square
bracket, space dollar i, space i from Lt, space five, space closed square bracket, semicolon
do, and within the body of the while loop we want to echo the value of i, and then follow
that within double parenthesis i plus plus, finally the final line consists of done.
Now things to note here are that the while and the do partner on the same line, separated
by a semicolon, you can do it either way, either with the two parts on separate lines
or the two together, separated by a semicolon.
The echo will generate the number zero to four.
The double parenthesized i plus plus is something we looked at in arithmetic expansion stuff
back in an earlier show, which I referenced earlier.
So that's a pretty simple while loop.
Second example is another code snippet, which will start with setting variable i to five
and then decrement it to zero.
So here we're using an until loop after the i equals five, and the test is in single
square brackets dollar i, space i from eq, space zero.
So until i zero, we're asking for, the do is on the same line with the semicolon.
We echo the value of i within the loop, and we decrement it in one of these arithmetic
expressions, double parenthesis, and finally there's the done, which closes the loop.
So the last printed value will be one, and then it'll be decremented to zero, and then
the loop will stop because the dollar i equals zero tests will become true, so that's
what it will stop.
Otherwise the test is false, so it keeps looping until it becomes true.
These increment and decrement operators, I think I just
said that they were part of the show I did earlier, they're not actually, I don't think
they were anyway, but I have referred to these before and given examples of them before.
Basically it just takes a variable and increments it, or decrements it, certainly referred
to the increment and decrement operators in that context, went through a whole list
of these sorts of operators.
So let's go to the conditional constructs bit.
There are three commands under this, under this heading, which have a conditional component,
and the commands are if, case, and select, but I don't think select is all that useful
to refer to just now, so I'm just going to look at if and case.
So the if command, you'll have seen these before anyway, I think I've used them many times
in script without really explaining them.
If command consists of the word if, followed by a space and some test commands, which
I've referred to as test commands, one, then on the next line, then, then some commands
which depend on that test being true, then if you want to do another test, then you
can use the word LIF, E-L-I-F, which means otherwise else if, sort of compressed together.
There's another set of tests and another then on the next line, a bunch of commands,
a second bunch of commands, and then these components are optional, which I haven't
really signaled if you look in the documentation, which I've referred to, the syntax is later
with a more complex way, but which explains which bits are optional, which are not, I decided
not to go to that level of detail here.
And you can also have an else portion where if the previous tests or tests don't return
true, then the else portion is executed.
You can put then piece on the same line following the test commands, separated by semicolon
as before, hopefully that covers if sufficiently to understand it.
I think most people will have got that already.
We haven't looked at in any depth at all, if at all, is the case command.
Case is also a testing type command making choices.
It consists of the word case, followed by a word, which is usually a variable, followed
by the word in, so case word in, then usually on the next line, you have a pattern list
followed by a close parenthesis, a right parenthesis, followed by a list of commands, followed
by two semicolons, then you can have pattern list two, command list two, two semicolons
and the same sort of thing.
You can repeat that as many times as you wish.
What it's actually doing is that the pattern list is being compared with the word as an
example coming up shortly.
And if it matches, then the appropriate command list is being executed.
If it doesn't match, then usually control pass on to the next pattern list and it will
be tested, but there are ways of changing that order.
So basically it, the first pattern list that matches the word will be, of course, various
things to happen.
It's possible to have multiple patterns in the list, in which case they're separated
by single vertical bar characters, character.
The patterns that you use are the glob patterns that we discussed in show two to seven eight.
And the pattern list is terminated by the right parenthesis.
You can, if you wish, proceed the pattern list with a left parenthesis if you want.
I've never seen anybody do that, never do it myself, but you can do that if you want.
This list of patterns, that'd be one or several, and the associated command list is known
as a clause.
There's no limit to the number of case clauses.
First pattern that matches determines the command list that's executed.
There's no default pattern, but making asterisk, the final one, the pattern that always, will
always match, achieves the same thing.
The clause terminator, we've seen double semicolons, but there's also semicolon ampersand
or double semicolon ampersand.
There's a little table here which defines what they mean.
Double semicolon means no subsequent matches are attempted after the first pattern match.
So if you match, then do the commands, then nothing more is done, the case is exited.
I forgot to say, actually, that the case command has to end with ESAC, which is case belt
backwards, otherwise the batch doesn't know where the end is.
I also forgot to say the same with the if, if ends with fi, which is, if it's belt backwards.
Let's see a pattern here.
Anyway, going back to the clause terminators, semicolon ampersand means that after matching
a pattern and executing the commands, execution is to continue with the command associated
with the next clause, if any.
I haven't got an example of it.
I haven't really used that myself, though.
I've not spent any time looking at it.
The double semicolon ampersand makes the shell test the pattern in the next clause, if any,
and execute any associated command list on a successful match.
So you should have had it executing the matching a pattern execute in the commands, and then
testing the patterns on the next clause, and if it matched, do the next one.
So you could actually make it test, make the case statement, case command test, then have
success, but then go on and do another test, which may or may not be successful and do more.
And if you keep using this terminator throughout the case, you could make it go and do tests
on a multiple level.
I can't immediately think of why you'd want to do that, but it's really because I've
not thought much about it.
A couple of examples of if and case.
So I've got example three, which is we set a variable fruit to the string apple, and
we test to see whether fruit is equal to banana.
And if we do, if it does, if it does match, then we echo some message about bananas and
check whether it's an apple and do the same again and kiwi and so forth.
And the idea was that for some reason or other, you don't know how to eat these fruit.
So it's explaining things like don't eat the banana peel, the skin, whereas if you like
to eat apples, you can eat it, eat the skin.
If you're eating a kiwi, you normally peel them first.
I do know people that eat the skin.
And if the fruit is not one of those, the tall then, well, you're on your own chum.
This is an example, a complete standalone example, which is bash 9x2.sh, which you can
play with if you wish.
It's got a bit more to it, it's got a loop in it.
If you're interested to try it out yourself, but it uses the if part to check whether
it's a banana, then it uses elif to see if it's an apple.
And then another elif to see if it's a kiwi.
And then if it, none of those match, we have an else branch, which is the not sure output.
Hopefully that self-evident, how that works.
Then example four is the same idea using a case command.
So we've got fruit equals apple to start with.
And then we do case of fruit, dollar fruit, that is, in, then we're matching the patterns,
banana, apple, and kiwi, and then asterisks, which is anything else.
And in the case of banana, we echo dollar fruit, colon, don't eat the skin, close, quote,
double semi-colon.
So if it's a banana, then it will stop at that point and exit the case statement.
And the same, same sort of idea.
Hopefully you'll, you'll see, personally, I would have used the case for this test.
Now that I've ever wanted to do this, take a test.
The case one to me seems cleaner and more understandable.
This again is an example that you can download and run for yourself, EX3.
So lastly, cyberleaf all round, we're going to look at a slightly strange aspect of bash,
which is lists of commands.
This is another sort of conditional thing, but it's not, it's not a statement as such,
it's just the way in which you lay out command.
So you can type bash commands in lists, and simplest lists are just a series of commands
where indeed pipelines, which we have not really looked at and need to talk about another
time, each separated by a new line.
So that's how you normally type stuff, you type it on the command line, you're hitting
new line at the end, et cetera, or in a script, you might type commands one after the other.
But there are other lists separated such as semi-colon, which lets you write several
commands on the same line.
The semi-colon is equivalent to the new line.
But there's also an ampersand, double ampersand, and a double vertical bar.
So the semi-colon is not under the ampersand and not relevant to decision making, so we won't
go into those anymore.
The so-called AND and OR lists containing the commands or pipelines separated by a double
ampersand, which is logical AND, double vertical bar, which is logical OR.
These are relevant to what we're talking about here.
So an AND list has the form, command one, double ampersand, you need spaces here, and then
follow that by command two.
So command two is executed if, and only if command one returns an exit status of zero.
You're going to expand this a little bit in a moment.
An OR list consists of command one, then the double vertical bar, and then command two.
Command two is executed if, and only if command one returns a non-zero exit status.
So here's how these lists behave.
The operators, double ampersand, double vertical bar, logical AND, logical OR, will short
circuit.
In the case of logical AND, an attempt is being made to determine the result of applying
a logical AND operation between the two operands.
They both need to be true before the overall result is true.
So this is Boolean logic, so A and B need to be true before the result is true.
If the first operand, that is command one, is false, there's no need to compute the second
result.
The overall result must be false.
So there's a short circuit, command two is never executed.
So it's a kind of an if, but without, in a more compact form, I guess you'd say, you'll
see it quite often, I think.
In the case of logical OR, then either or both operand, the logical OR operation can
be true to give an overall result of true.
So if command one returns true, nothing else needs to be done to determine the overall
result.
Whereas if command one is false, then command two must be executed to determine the overall
result.
So in other words, if command one returns false, then you do command two.
I've used these a lot in the past.
I've seen people use them and thought, oh, that looks cool.
What does it do?
Oh, yeah.
But not really understood why, and that was my attempt to explain it so that you have a
little bit more insight if you get into using it.
So there's some examples of using this type of thing.
It's common to see these used in scripts as a simplified decision with an explicit test
as command one.
So for example, you might see something like open square bracket space, hyphen e, space,
and then the name of a file, space, close square bracket.
And the hyphen e is an operator which checks to see whether the file that follows it exists
or not.
We're going to look at this operator in the next episode.
So that test is then followed by double vertical bar, the logical or, and then exit space
one.
So if the test finishes with a non-zero result, that's command one.
It means the file didn't exist.
So we exit, in that particular case, for exiting, exit can take an argument, which is the
return status to be returned by the script, so exit one.
You wouldn't type this on the command line because you'd log yourself out.
Exit one will make your script exit with a false result.
So that's a common thing you see.
Maybe you're writing a script and your script depends on a file.
You'd put these sorts of tests in quite early on to say if this file doesn't exist,
well there's no point in continuing, it's something broken.
The only trouble with this is that it doesn't tell you the user of the script why it's
just exited without doing anything.
So it is possible to execute several commands instead of just the exit, and you do that
by enclosing them in curly braces.
So you've got a similar example with a similar test, and after the logical or, operate to
the double vertical bars, we have curly brace space, you have to have spaces after these.
In fact, it can be a space or a new line, and other things.
So after the space we have echo, unable to find, then the name of the file, semi-colon,
exit one, semi-colon, you do need that final semi-colon because it's a list of commands
here, and the curly, close curly bracket is taken to be a command.
You can write it on multiple lines, and you can write it instead of using the square brackets,
you can use the test command.
So the same thing written out again using test would be test space, hyphen e, space, the
name of the file, space, double vertical bars, space, open curly bracket.
Then on a new line, echo, unable to find, and then the name of the file.
Next line, exit space one, then on the final line, the close curly bracket, curly brace.
So that's a bit more readable, I would say, so that's not, that can be a useful thing
to do.
So as possible as that command one in these types of lists, to be, to use anything that
returns a zero or non-zero as a result.
So you could use the graph, we used earlier, graph minus q, space minus e, single quotes,
barra, banana, dollar, close quotes, fruit.txt, and then follow that with double ampersand,
echo, found a banana.
That's equivalent to the if example we used earlier on.
But in my opinion, it's a lot easier.
It's a lot clearer and more understandable, let's say, if you use an if, in that case,
it's more plain that you're performing a test and you're going to take this option if
it is true.
This one is a bit more obscure.
I do use both, but I wouldn't use this form myself when I was doing something like this
if I was searching for banana, which I do often, of course.
Anyway, that's the end.
Bye.
You've been listening to Hecker Public Radio at Hecker Public Radio dot org.
We are a community podcast network that releases shows every weekday, Monday through Friday.
Today's show, like all our shows, was contributed by an HBR listener like yourself.
If you ever thought of recording a podcast, then click on our contributing to find out
how easy it really is.
Hecker Public Radio was founded by the digital dog pound and the infonomicom computer club
and is part of the binary revolution at binrev.com.
If you have comments on today's show, please email the host directly, leave a comment on
the website or record a follow-up episode yourself.
Unless otherwise stated, today's show is released on the creative commons, attribution,
share a life, free dot org license.
