Never say "If" writing a Bash script! (Exit codes & logical operators)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I want to talk about something that really separates elegantly written Bosch and shell scripts from not so elegantly written ones here's a rule of thumb that I've mentioned before on my channel but I want to explain it and that is when you're writing a shell script 95% of the time don't use if statements that sounds like a weird thing that's a basic thing in programming you know if this is true do that or do that if it isn't you know that's a very common thing but when you're running shell scripts there are logical operators that exist that make it mostly unnecessary to do that in most most of the times not all the times there are some times where you do want to use if statements but let me explain so just in general here are the logical operators I'm talking about and you've probably seen them if you write written scripts but knowing how to use these will make the difference it will make your scripts much more elegant you'll have you'll be able to remove some ugly if statement and replace it with one line okay here's one and and here's another pipe pipe or or here's another semicolon and here's the last one single and what is the difference between all of these you probably see these every once in a while let's talk about the difference and then we'll show you I will show you how you can make scripts a little more elegant it's just good-looking it's very shell like it's very bash like to how to use these properly okay so here's a basic example let's talk about the most basic one is probably semicolon semicolon means run a command and then you provide a semicolon and then it will run the command afterwards so let's say here's an example echo hello there okay so if we what we can do with semicolon is we can chain commands together so let's say we have echo hello there and echo general Kenobi okay so we have these two commands and if I put them together with semicolon it will execute both of them it will execute the first one and then the second all right that's what semicolon does and it's pretty promiscuous it's pretty much always gonna work you know it's not gonna change its mind half way through like the other ones will what actually that's the magic of the other ones but just to be clear semicolon is basically the same thing as having a new line so if if in a shell script we had something like this echo blah blah blah and echo blah blah blah this could be re-written as the following it could be re-written as that you could get rid of the newline and put a semicolon between them that's basically the same thing okay but let's talk about the other logical operators because that's where the magic happens so first off and and if you replace semicolon with an and it's gonna look like it did exactly the same thing it did actually do the same thing but the logic behind it is a little different and and is picky and and only runs the second command if the first command succeed it only in that circumstance if the first command succeeded so here's an example instead of echoing something let's try and cat a file because that's something that can go wrong for example I can cap my Z profile and it'll print out that file so that program that command ran successfully but if I try and cat out my bash profile well I don't have a bash profile that command failed so here's the difference between semicolon and and err well if I say let's go back to catting out my Z profile again I have a Z profile and then I say echo this is my profile okay so I can print that out or cap that out and then if I have a semicolon it will show this little thing at the end this is my profile it ran that command as well and I can just in the same way as I did with those two echo commands I can do the same thing with and and it will run both of the commands but the difference is what if here's here's the case that's different what if instead of trying to cut out my basket or my Z profile I cut out my bash profile which again does not exist if I do that since we're using semicolon I try and cat this out doesn't work it fails but semicolon it's just gonna run the command that's next so it's gonna still print out this is my profile I don't really want that to do that so I'm gonna do is I'm gonna replace it with and an and the difference here is that it's gonna try and cut out bash profile that command fails and and and only runs it will only run the second command if the first command succeeded so in this case it will not print out this is my profile and this is probably the preferred way to do it because we only really want that label if the profile prints out okay so that's what and and is for so it runs only if the first command was successful whereas semicolon runs all the time now pipe pipe or or is the opposite of and and it only prettiest so for example if you have this let's say well I'll rewrite this let's say I rewrite this cat out bash profile or print out file does doesn't exist okay now in this case what that did does is it tries to cut out the bash profile and when we get to you or or pipe pipe it says okay I'm gonna run the second command only if the first command did not succeed in this case it didn't succeed so it printed out the second it did the second command file does not exist right but if we switch this file to let's say Z profile which does exist so this command will succeed now you'll notice that the second command did not run that's because pipe only runs the second command if the first one failed okay so that is the difference between these three now you might already in your brain you might already be thinking okay I can repair the statement with this and that's true I'll show you that in a second but just to be clear there's one other logical operator and that is single and which is utterly different from and and what this is just to be clear let's have a case let's say the command sleep 5 which by default will wait for 5 seconds and then you know continue you can do whatever else so we can chain that that together with an echo command so all done so what this is going to do it's gonna wait 5 seconds then it's gonna echo all done now the difference between these operators and and are these three on the top is that all three of these wait for first command to be done then a tren runs the second commander runs it if it failed or succeeded the difference between single hand is that single and we'll start the first command and then it'll just start the second command doesn't matter if the first commands done or not so if we run this you'll see that all done actually prints out immediately once this command starts and then a couple seconds later you'll get this message that says that the sleep command is done right now to be clear this should be the process number of the the first command that it temporarily abandoned which you can do stuff with that but that's another issue okay so let's talk about a real-life implementation of this so I'm gonna I'm gonna write an example shell script and here's the here's the implementation I want to do let's say for example let's replace an if statement that we might be tempted to use with one of these let's say so there's something on most systems will have what's called an editor variable defined so in this case my editor is neo vim alright so an editor variable usually you'll have them on systems they just define what your favorite text editor is that a program might open up your favorite text editor to do something but let's say in mini scripts there are some systems where editor variables are not defined so you need you need to basically check if that variable is assigned and if it's not you might want to assign it in the script okay so here's how you would write something in elegantly with a if statement you might be tempted to do something like this if will do it very in elegantly if the browser is equal to nothing okay then do the following set or not browser editor sorry I don't know why I'm thinking a browser sometimes people use the browser variable as well so if the editor is equal to nothing then set the editor equal to we'll say Nano is the default editor because I don't know I guess people can usually use that and then I'll close my if statements so I will say this is ugly bachelors syntax is very ugly when you do this because look you have this third thing in brackets you have this semicolon then then you'll always forget all this kind of stuff it's just a big annoyance and of course it's three lines you could actually put it on the same line with some semicolons and stuff but this is how you typically write it there's a much better way to do this actually well let's make sure that this script will work first off so I'm gonna run the script as I said my default editors in vim and it's gonna print out in vim because what I have this doing is checking to see if there's no editor variable and whatever it ends up as we're gonna print it out but let's say I unset my variable or unset example unset editor so let's say I unset my editor variable so now I have no editor and I run this command again example and it is now gonna print out Nano again what it did is that check to see oh look this editor variable is equal to 0 so assign it to Nano okay otherwise it would have run in vim okay now how can we more efficiently write this just with the error code things here's how here's what you can do well first off actually aside from it error codes this is a lot of times people will do this if a variable is equal to some you know empty string or something a more elegant way of writing this is with the Z tag so if you just write Z editor then Nano so that'll be that you know the dash Z basically means if this is equal to nothing right technically very there's a difference between a variable assigned to an empty string and an unassigned variable but that we won't talk about that here but anyway so in this case basically this is exactly the same as this so that's one optimization but here's another thing actually I'll just show you what it looks like and you can figure it out yourself so Z editor that is if editor is equal to 0 this is implicitly already an if statement you don't actually need F or then or else or LF or the end of the if statement you can just say this editor equals Nana okay these lies this if statement that can be more tersely stated as just a single line that is if that if there's no editor variable assign it to nano and this is gonna work exactly the same way okay or if we have if we have a our editor is equal to in vim we can run this Ellen look it's gonna be in vim or if our editor is equal to I don't know normal then it's still gonna work right so basically most if statements can be replaced with just one of these things if you actually check just check a variable and do this or for any command you can put here and then just have and and or or or after it and or pipe pipe after it and check to see or do whatever you're supposed to do right so that's a more elegant way of doing it so here's another I will give you one minor example sort of a not a brainteaser but something to think about now I want to talk about one more example I'm not gonna write out write out a whole example for you but one that came to my mind that's in one of my scripts here is my mutt wizard script and just as an example here's an a real-life implementation that actually makes makes using Eric exit codes and the sort of logical operators much more efficient than the alternative here for example this is my mutt wizard where I'm getting I'm having the user input information about their email account and then we try to connect to it and finalize it and do some things and if anyone if anywhere in that process it fails I want it to delete the count of the account information so it doesn't mess things up okay so that's one real-life implementation now you don't need to know what all these functions are but I've defined a bunch of functions in this script for example I asked the type Oh what type of email do you have what is the info asked info has asked for that then we try to connect to a blah blah blah now the important thing is what I want is I want it to follow I wanted to do all these commands it does ask type it asks for the type and we have and an here meaning only if that succeeds do we go to the next one then we have n in here only if these two have succeeded do we go to the next one and then we have and an here only if these two succeed do we go to the next one and if there's an error code think about it this way let's think about it linearly let's say there's an error in this function okay what it's gonna do is it's gonna this bash or whatever your interpreter is is gonna get to this next logical operator and it says ah there was an error code before this is an end and therefore I'm not gonna run this command and then it's gonna get here and it's gonna say the same thing okay the last command failed so I'm not gonna run this then it's gonna get to this the pipe pipe the or statement and it says ah yes the last command that ran failed so I'm going to run this delete function so this line here is an example of a very efficiently written series of functions where instead of doing something stupid like Oh check if this command run ran successfully and then check this it's a results and stuff like that no now screw that just use exit codes just use these logical operators and you don't have to have anything too fancy it's just a bunch of commands together it just works very well anyway so that's about it that's enough for this video I you know I said a bit ago I want I wanted to do like shorter videos but I realized that I've just been going so hard for these past couple ones that they take a little longer than I intended but anyway that's about it I'll see you guys next time
Info
Channel: Luke Smith
Views: 206,249
Rating: undefined out of 5
Keywords: bash, shell, sh, posix, write, code, exit, error, &&, ||, semicolon, and, or, logical, operators, efficient, terse, elegant, lines, free, software, floss, open, source, linux, gnu, iterm
Id: p0KKBmfiVl0
Channel Id: undefined
Length: 14min 50sec (890 seconds)
Published: Thu Mar 19 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.