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