Files
hpr-knowledge-base/hpr_transcripts/hpr2639.txt

202 lines
18 KiB
Plaintext
Raw Normal View History

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