- 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>
202 lines
18 KiB
Plaintext
202 lines
18 KiB
Plaintext
Episode: 2639
|
|
Title: HPR2639: Some ancillary Bash tips - 9
|
|
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2639/hpr2639.mp3
|
|
Transcribed: 2025-10-19 06:55:47
|
|
|
|
---
|
|
|
|
This is HPR Episode 2639 entitled Sumansillary Bash Tips 9, and in part of the series Bash
|
|
Cripting.
|
|
It is hosted by Dave Morris and in about 22 minutes long, and carries an explicit flag.
|
|
The summary is making decisions in Bash Part 1.
|
|
This episode of HPR is brought to you by an honesthost.com.
|
|
With 15% discount on all shared hosting with the offer code HPR15, that's HPR15.
|
|
Better web hosting that's honest and fair at An Honesthost.com.
|
|
Hello everyone, this is Dave Morris, welcome to Hacker Public Radio.
|
|
So today I'm making my ninth contribution to Bash Cripting series.
|
|
I've been doing a bunch of episodes which I have entitled Bash Tips various subjects.
|
|
I wanted to look at how Bash makes decisions, because this is something that I've referred
|
|
to many other shows and you've seen in lots of other contexts, but I thought it would
|
|
be useful to be a bit more formal about it or quite a complex project though I realised
|
|
I'd written the sketch out a single show and I started to design it and realised that
|
|
it's more than one, then it was more than two, and I just recorded the audio for this
|
|
one and found that it turned out to be about an hour long, which I'm sure would be stunningly
|
|
unpopular.
|
|
So what I'm actually going to do is chop this particular show, which I thought would be
|
|
short, haha, into two, so I'm just re-recording the preamble here so I can do that.
|
|
What I want to look at is, in this particular one, the tests that Bash offers to allow
|
|
you to make decisions in loops and in conditional statements and so forth.
|
|
And I'll go into loops and conditional constructs and a few other things in the next episode.
|
|
So let's start by looking at the types of tests that Bash offers.
|
|
There are four main types of tests in a very general sense of test that can be used to make
|
|
decisions in Bash. First of all, there are expressions which you use a command called test and
|
|
there are the open and closed square bracket operators. We'll talk about those in a moment.
|
|
It doesn't also shell arithmetic and a newer addition to Bash is the pair of operators which
|
|
consists of two open square brackets and two closed square brackets. Finally, there are Bash
|
|
functions and commands and programs and so forth, which can be used as tests in various ways.
|
|
Now in order to explain this, I'm having to refer forward to commands which haven't yet explained
|
|
is because everything is sort of meshed together so you've got to start somewhere.
|
|
So let's start with the first category which is the single open and closed square bracket operators
|
|
and the test command. So you do use them by writing open square brackets followed by an expression
|
|
followed by closed square bracket or test followed by that same expression. Both of these are
|
|
the same. The only difference is test followed by space and the expression is all you have to type
|
|
whereas if you started with an open square bracket and the expression you must remember to put the
|
|
closed square bracket in. These are built-in commands so a square bracket can be a command in Bash
|
|
and they're inherited from its predecessor, the Born Shell. There's a link to the Gnome manual
|
|
on built-ins for all of the details here. When I say built-in, it's actually part of the Bash
|
|
shell itself rather than being a program that you invoke. Since the open square bracket and
|
|
the closed square bracket are effectively commands and commands have to be separated from
|
|
their argument by at least one space then this is something you have to do if you're using
|
|
this form in a test. It's a common error to omit these and there's an example which shows an if
|
|
statement and it's if space open square bracket dollar i space minus gt space zero closed square
|
|
brackets then we call on space then. Now there were no spaces after and the open square bracket
|
|
or before the closed square bracket and if you did this you would get an error message which says
|
|
Bash square brackets two command not found. Well this assumes that the variable dollar i contains
|
|
value two but what's happened is the left square bracket and the value in variable i have been
|
|
concatenated because there's no intervening space so this would not work. The expression between
|
|
the square brackets or indeed following the test command is referred to as a conditional expression.
|
|
There's lots of documentation in the GNU Bash manual which I've referenced in the notes and
|
|
we'll be looking at this this subject a little later on in this group of shows. Let's go into
|
|
the second category of test which is shell arithmetic and we looked at some aspects of this in show
|
|
1951 when we looked at arithmetic expansion and mentioned the arithmetic expressions available
|
|
in Bash. So we looked at expressions such as an echo followed by dollar two open parentheses 42
|
|
slash five that's 42 divided by five closed parenthesis closed parenthesis and the answer is eight
|
|
and that would be echoed. So that was how you did an arithmetic expression the dollar on the front
|
|
made it so. It's also a form that you use in a different context which consists of two open
|
|
parenthesis and expression an arithmetic expression and two closed parenthesis. I've written it out
|
|
with spaces after the brackets and before the after the left brackets and before the right
|
|
brackets but you don't have to have to provide them. It's one of the areas of Bash that can be a bit
|
|
confusing when to use spaces and when not that's partly why I'm referring to it now.
|
|
Now the thing that can occur in this arithmetic expression can be used to assign values and to
|
|
compare them and when you're using this in the context of a test then the result of the arithmetic
|
|
computation is used to obtain a true or false value. The value of it if the value of the expression
|
|
is non-zero then there's an example coming soon so hopefully that will be clearer then the return
|
|
status is zero. Now in Bash any return status and I'll explain what return status means in a moment
|
|
any return status of zero is regarded to be true. So if the value of the expression is zero
|
|
then the return status is one which is false. Any non-zero value as a return status is false.
|
|
Now I find this a little confusing or harder to remember so I wrote a little script which you
|
|
can download as Bash9EX1.sh if you want to and I ran it and captured the output. The listing in the
|
|
in the notes consists of a cat command which cats the contents of the file and it contains a
|
|
for loop. I'm not going to talk about for loops in this particular show I probably need to cover it
|
|
later but I'm sure you have the the you understand this already or you can soon pick up what it does
|
|
and it goes for i in and then there's a brace expansion expression which we covered back in the
|
|
in this series which goes from minus three to plus three. So this is a loop which will change the
|
|
value of i starting from minus three in steps of one up to plus three. So in the loop we echo the
|
|
value of the variable i followed by a colon and a space we use echo minus n which means don't put
|
|
a new line on the end. Then here's the meat of the thing there's an if command immediately follows
|
|
this which consists of if open parenthesis open parenthesis i close parenthesis close parenthesis
|
|
semicolon space then. So if the result of that is true then we want to echo the variable
|
|
that the inbuilt variable dollar question mark and the word true and then there's an else section
|
|
where we echo dollar question mark and the word false. So when you run that he starts off and
|
|
you get the value printed out minus three colon and then a zero which is the result of the test
|
|
and the word true minus two results in two minus one gives true as well zero results in one as a result
|
|
and result status i should perhaps say and the word is false and then it flips over to true again
|
|
values one two and three each get true. So all values except for zero result in a zero which is
|
|
means true. The expression in double parenthesis can be a numeric assignment so if you did it within
|
|
the double parenthesis x equals 42 then it will set the variable x to the value 42 and the
|
|
where they have spaces in there or not is entirely up to you but there's a result return from that
|
|
expression and that assignment which is 42 and because the business of what final result comes
|
|
from an expression is used as a true false value then because 42 is non zero then it's regarded
|
|
as true. The expression can also be a comparison here we have x equals equals two equal signs 42
|
|
in the the double parenthesis. This expression will have a non zero value and will return the result
|
|
true so it can be used to test whether the variable x contains a value 42. You can only use it
|
|
for comparing integers not for strings or anything like that but it could be quite useful. We'll see
|
|
there's this later on there are other ways of doing this but this is one way which can be quite
|
|
elegant. In these expressions you can also have Boolean or logical operators such as two ampersands
|
|
which means and logical and and two vertical bars which means or and so it's possible to write a
|
|
more complex expression again in double parenthesis x equals equals 42 and ampersand ampersand y not
|
|
equals that's exclamation mark equals 42. This will be true when x is 42 and y is not. Have a
|
|
look at the arithmetic expression sections of the GNU bash manual if you want to see more examples
|
|
and maybe get a better understanding. Hope what I've said has been clear but in case it hasn't
|
|
that could be a good source. So the next category is the double square brackets, double open double
|
|
closed square brackets. This consists of something very similar to the single square brackets type
|
|
where you start with two open square brackets then you have an expression and then you have two
|
|
closed square brackets. The double square brackets are actually a command. To be entirely
|
|
strict about it it's a keyword but I'm not quite sure what the significance of that is. The types
|
|
of expression you can use here are different and the this form of test is referred to as an extended
|
|
test and this is the one that got added to bash a bit later on in its history and it's reference
|
|
the documentation in the GNU bash manual in the notes. So you've got to have spaces after the
|
|
open double square brackets and before the closed double square brackets because it's a command.
|
|
One of the differences between the form using single square brackets and double square brackets
|
|
is that with the former you should enclose the left operand in double quotes. So there's an
|
|
example here of single open square bracket space double quote dollar N double quotes space
|
|
hyphen EQ that's the equals operand operator I should say space 42 space closed square bracket.
|
|
So you need to enclose that variable within double quotes in order to get substituted
|
|
properly and the reason for doing that is if the variable is null or empty and there are no quotes
|
|
the expression will after being scanned for the first time will turn into open square bracket space
|
|
hyphen EQ space 42 space closed square bracket which makes no sense and is illegal in
|
|
the course your script to break stop at that point. However if you want to do the same sort of
|
|
thing with the double bracket form then you can emit the quotes because it parses it differently.
|
|
I've made a reference to the GNU bash manual where it says word splitting and file name expansion
|
|
are not performed on the words between the open double square bracket and the closed double square
|
|
tilde expansion parameter and variable expansion arithmetic expansion command substitution
|
|
process substitution and quote removal are performed and we've covered pretty much all of these
|
|
issues in other episodes of these bash tips shows so hopefully that was that was meaningful to you.
|
|
The last form of test or the last type of thing you can use when you're
|
|
testing is a bash function or a command or a program and we haven't really done much about how
|
|
to write bash function though there have been some episodes talking about useful functions which
|
|
are not part of the bash tips sub-series functions can return status values and such functions can
|
|
be used as test commands to control the commands that we're going to cover soon. So if you
|
|
look at episode 296 I'm talking about a function I called yes underscore no you could use that in
|
|
such a context and there are examples in that show for for doing that very thing and our commands
|
|
like grep can also be used in a in a test that's a that's a standard command standard unix command
|
|
so you might write something like if space grep space minus q minus q means produce no output be
|
|
quiet space minus e minus e is just the thing that says here's the test expression you want to use
|
|
you don't actually have to use that but I like to to do so to make it unambiguous and in my case
|
|
the thing that's being checked which is a regular expression is a carrot or a an up arrow or a
|
|
circumflex character which which means the start of the string the word banana and then a
|
|
dollar which means the end of the string or end of the line all in single quotes and then the
|
|
next argument is fruit dot txt so what we're doing here is to check whether the string banana
|
|
exists as a as a complete entity on a line of its own inside that file fruit dot txt so after
|
|
that grep expression we have semicolon the word then that's part of the if statement and then we
|
|
would echo some string like found a banana finish the thing with an fi if grep finds the string
|
|
in the file it will exit with a zero status so in other words it returns a value of true
|
|
and this will cause the if command to execute the echo command so instead of grep it's possible
|
|
to run a script or indeed a compiled program in some some language that you use and do it in
|
|
the same sort of way but the script or compile program needs to return a status value which
|
|
signifies success or failure in the same sort of way most provided tools do this if you're writing
|
|
something yourself you also need to be careful about doing the same sort of thing interestingly
|
|
bash provides two commands which are called true and false which could be programs which
|
|
often are existing slash bin slash true and slash bin slash false but most likely they're built
|
|
in commands it depends on which version of Linux or other operating system you're using in my
|
|
case I find that both of these exists so I use the command which space true space false which is
|
|
asking what are these things looked at as items within the file system and I get back slash bin
|
|
slash true and slash bin slash false and there's the command type type space true space false which
|
|
is asking what type of things are true and false and it comes back saying true is a shell building
|
|
and false is a shell building which means they're part of bash itself so the true and false
|
|
commands simply return the values true and false as status values if you have both like I do
|
|
then the one that gets used is it will be the built in one by default now in the next section
|
|
and when I talk about looping next sections I should say looping contracts and conditional construct
|
|
then I use a generic indicator of test commands and these are expressions that return a status of
|
|
zero for true or non-zero for false in the way I've explained already so having talked a lot
|
|
about return statuses and stuff I thought it was worth expanding a bit on what this actually
|
|
mean because it's not complete the obvious I hesitated about whether I should start with this but
|
|
I thought it'd be more confusing if I did so I've left it till the end there's a thing called
|
|
the return status of a command if you use the echo command and you echo the number 99 say
|
|
it'll display the number 99 but it returns a status of zero which it denotes value true
|
|
and this status is held in the special batch variable dollar question mark and you can test that
|
|
or display it every command resets the status so every command that you issued generates the status
|
|
so you've got to be careful because the value that you might be interested in could be lost
|
|
so there's an example here that says uses the echo 99 the answer comes back 99 as a displayed item
|
|
then I echo dollar question mark and get back zero so that means that's the true value
|
|
that came in other words the echo command worked fine if you deliberately make echo fail so I typed
|
|
echo space open parenthesis I get back a bash error and then echo dollar question mark and
|
|
I get back the value to so that signals that the echo failed in some way so you can capture that
|
|
variable store it in a more in an ordinary variable and use that to determine whether the thing you
|
|
just did in your script worked or not without the the test itself deleting the value that you're
|
|
looking at now show show another example where the false command generates a status of one which is
|
|
false but the act of actually looking at dollar question mark changes its previous content so
|
|
the little snippet here issues the command false and then echoes dollar question mark gets one
|
|
which is what I said it would do but the process of running that echo changes the status so if you
|
|
then type echo dollar question mark again you get back the value zero because the echo worked
|
|
echo return to true result but the false didn't anyway that's the end bye
|
|
you've been listening to hecka public radio at hecka 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 hecka public radio was founded by the digital dog pound and the infonomicon computer club
|
|
and it's 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 comments attribution share
|
|
light 3011
|