Initial commit: HPR Knowledge Base MCP Server
- 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>
This commit is contained in:
312
hpr_transcripts/hpr2649.txt
Normal file
312
hpr_transcripts/hpr2649.txt
Normal file
@@ -0,0 +1,312 @@
|
||||
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.
|
||||
Reference in New Issue
Block a user