- MCP server with stdio transport for local use - Search episodes, transcripts, hosts, and series - 4,511 episodes with metadata and transcripts - Data loader with in-memory JSON storage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
313 lines
19 KiB
Plaintext
313 lines
19 KiB
Plaintext
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.
|