 Well, it's that time of the week again. It's time for Chitchat Across the Pond. This is episode number 765 for April 15th, 2023. And I'm your host, Allison Sheridan. This week, our guest is Bart Bouchotte with another installment of Programming Based Health. How are you doing today, Bart? Hi, I'm doing good. A little bit more rained on than I wanted to be, but yeah. Well, I'm going to use a quote from you. We have this big, strange yellow thing in the sky and nobody knows what it is. It's the first time it's like we've awakened to sun in months. I awakened to sun too, in fairness. It was just the weatherman said, as the day goes on, cloud will build and rain will arrive by what did he say? Late evening, which apparently is four o'clock. Oh, I grumble with his definition of late evening. Yes. Anyway. Before we get stuck in, we wanted to make an announcement here to make sure that everyone knows that there's a link to the show notes if you're listening for every episode in the podcast feed. So if you're listening to this, look in your podcatcher, there's a link to be able to take you to Bart's fabulous show notes. It's a little bit convoluted because it sort of goes to my site and then back out to Bart's, but you can get there and you can get all of the tutorial show notes. The other thing is that we want to make sure you know that you can join in the conversation with us and other Programming Based Health learners by joining the Podfeat Slack. Now, it sounds kind of funny to get there through Programming Based Health, but work with us here. There's a channel called hashtag PBS and that's where all the little nerdlets live and chat about Programming Stuff and it's a lot of fun in there. And so if you want to talk to Bart and me and other people, Bart dips in and out, but I'm in there pretty regularly and there's a lot of people in there smarter than me. So that's really easy to get to. It's podfeat.com slash Slack. Excellent. Yes. And it's a good community with good people and yeah, it's got quite lively. So nice to see you. Yeah, the reason we're bringing this up is because we've had a lot more focus on this show lately. A lot of people writing to us and getting excited and a bunch of people we've never talked to before joining the PBS learners that we set up the organization in GitHub. But a lot of people say, but how do we talk to other people? And how do we talk to you? And we're like, oh, we don't ever say that on this show. And it's kind of strange, but it seems that the two topics that have really set the series on fire are Git and Bash. And Git, I was expecting some traction on. Bash is a surprise, but it's getting a lot of traction. People really are tickled by it. We're getting lots of comments, lots of questions, people sharing notes together. And I am finding what I've found in almost every part of this is most of the people listening already know how to do the subject, but are learning more because of you. And one of the, Ed Howland is a recent joiner of this. And he said that he said, I've been using Bash for years, but I cannot believe how much I've learned from Bart. And Bart, you had a great response to that. Well, I'm basically about five minutes ahead of the class because I too have been writing Bash scripts for years, but it's always, you're always trying to do something. And so your goal is to get to something done. And so you go to Stack Overflow and you copy and paste it in and it looks semi-sane. So you go, give it a go. Oh yeah, that's what I want, great. But if you say to me, why is it dollar star, not dollar at? Or why is that quoted or why is that not quoted? A lot of the time I go, internet said so, it works. But you can't do that in this series, right? You, your job here is to be the every person and you're very bloody good at it, which means I am terrified of arriving for an episode without being able to answer the obvious question. Why? Oh, okay. If I type it and I can't say why, problem. And so you have to study that and then you ended up explaining to us and then we get to know that, that's really cool. Well, that's fun. Yeah, so I'm learning so much, so much. Today's perfect example. Speaking of being five minutes ahead of the class, I have not done the last installment's bonus homework because at 2.59 PM, Bart, I started at three, at 2.59 PM, I figured out why my homework from the week before, two weeks before had not been working. And I have, it's not that I haven't been working on it. I've had my code, your code, side by side by side. And we actually talked about it the last time that I had to use that IFS thing. I had to change IFS and change it back and you said that was a bad smell. I have been searching for why, for what is that? Now three weeks, trying to figure out why. And at 2.59, I realized when you do this select, if you don't put the name of the array in quotes, then items in the array that are two words, I have a space as a separator become two separate elements. Yes, when they expand out, that is, yeah, the quotes are important. So I could test the array and it would tell me, yeah, more bacon was one thing, but as soon as it did the select, it would be more and bacon. And I have been fighting that until 2.59 today, finally saw it. And the same would happen with a for loop. So if you did a for in, it would have come up as once through the loop for, was it smoky bacon or something? So once for smoky, once for bacon. Well, I had a completely different way of doing it and if then, blah, thing going on and it didn't work there. So I changed it to a while loop the way you did it and it still didn't work. I finally, I went through and I used your code with my menu to see if it would work. And of course it worked just fine. And I, yeah, but I finally saw it at 2.59. So I have not yet done this challenge, but that challenge looks pretty easy. So I may even figure it out today. Well, to be honest, that one was kind of a layup for the one you're getting at the end of this. So you can skip it and go straight to the one at the end of this, to be honest. Cause this is really where I want you to go. I love the challenges. I love them. They get me fired up. I want to play. I wake up thinking I'm going to work on this and then to go, oh, first I got to do that and that and that and that and then it's Thursday. You might recognize yourself in this one. Part of the challenges so that I know I'll make you smile. I added in a little joke that you will have far too much fun with. So. Oh, I like it. I like it. I do want to say that you have completely dragged me into your madness. I posted in our Slack at ponfi.com slash Slack that the other day I needed to create, just create a text file with something in it. And I opened the terminal to do it, Bart. Yay. This is a good sign. I approve this message. I guess, but I was just like, what's happened to me? It was easiest way to do it. Yeah, exactly. Right, well, what we are spending our entire installment on today is getting better at doing command-learn arguments. And along the way, I'm going to do one of those things I do where I've told you some stuff, but I'm very careful. I've tiptoed around certain words in my descriptions. I haven't told you an untruth, but I have definitely not told you the whole truth. So I'm about to reveal that without knowing it, you have been using standard POSIX variables. So POSIX is like a super set of a whole bunch of shell scripts because POSIX is the attempt at having it not become a complete mess. So the POSIX standard tries to say that the hope was that every single Unix and Linux would be POSIX compliant, which means that if you stick to POSIX, your shell script will work universally. Okay. And I'm not sure we've arrived exactly there because the only major operating system that's POSIX certified is the Mac. Unless you're living in like the banking sector where stuff like, oh, what's the... Some of the big Unix, the HP UX, HP Unix and stuff, where those things are still in use, they're certified POSIX. So you have certified POSIX, you have verified POSIX, which is basically it passes all the tests. And then you have sorta kinda POSIX. And I think a lot of people are probably cranky that Linux is sorta kinda POSIX. So it's like mostly POSIX. It's a bit like HTML3, or sorry, HTML5. It's like every browser does most of HTML5, but I don't quite do it all. And POSIX is a bit like that. But anyway. So being mostly POSIX, does that mean if we write something POSIX compliant on the Mac, it might not run on Linux? Or does it mean the other way around? It means there's more... Yes. If you're in POSIX land, you're on the safest ground you can be. But at the end of the day, these computers are built by humans and they all have their foibles. Okay. Well, we gotta try though, right? We gotta try. But a bunch of the stuff we're doing today is different to how it would be if Bash did it. Not because Bash is schizophrenic, but because Bash has to do the POSIX stuff to be POSIX compliant. And so we're gonna learn about some variables that don't know if they're an array or a variable. They're like a quantum variable. If you ask them a stringy question, they'll be a string. And if you ask them an array question, they'll be an array, but they're kind of both and they're kind of neither, which is a bit odd, but that's the POSIX standard for you. So that's why two of these variables are weird. It's not Bash's fault. It's POSIX. But anyway, we'll get to that. So it is all about arguments. That is our biggest thing today, is we wanna make our shell scripts behave like terminal commands. They should do things the terminally way so that they can slot into other, your own and other people's terminal shenanigans. If you do things the same way as everything else, it's just easier. People don't get confused. Your stuff just works. It's just, you know, when in Rome, do as the Romans. First thing I should say is you will find in the zip file for the show notes the solution to the challenge. And to be honest, it's extremely by the book because all I asked you to do was to add an optional argument to the existing menu script and the argument would be a rate limit. So if you don't pass the limit, you should keep taking order, you should keep taking items for the order until the user chooses to say they're finished. If there is a limit, then you should cut them off when I guess their virtual tray is full. I think you're sort of describing the requirement, including the how you did it, because I don't think you were that specific. So what you said, but you didn't say that you had to set an argument. It says update your solution to, wow, I'll wait a minute. No, maybe it did, except an optional argument limiting the number of items. Yeah, I've pretty much copied and pasted from one to the show notes in the other. So do you mean that the user of this shell script has to set the argument in an interactive way? Is that what you were asking us to do? Well, so basically when you run the shell script, you can optionally pass it an argument that is a number. Okay, okay, I misunderstood. I thought it was just saying, I can set this thing that you're only allowed to have three things for breakfast and then the response comes back and says, hey, quit eating so much or something like that. Well, I guess you could be snarky, right? I didn't tell you what to do when people reach the limit. Okay, okay, I understand better now. Okay. Yeah. Like I said, I finished the other homework at 2.59, so I just read this very quickly. Yeah, I don't use anything in my sample solution that we haven't seen quite a few times already. So it's extremely by the book and there is an infinity of ways of doing this, right? Because at the end of the day, you're going to default your limit to some value that represents unlimited. Then you're going to check to see if there was an argument. You're going to check to see if the argument is sane or not. And then if it is, you're going to change the limit from your default that means there is no limit to whatever the user said. And then in your loop, where you're going through your select over and over and over again, you're going to have to add a conditional to check, should I be applying a limit? And if I should be applying a limit now or not yet. So it's basically a bunch of if statements is what it comes down to. So the main thing I sort of wanted to draw your attention to in my sample solution is that I chose to represent no limit by an empty string. So I set my limit to an empty string to represent there being no limit. And the reason for doing that is it means that you can use the minus Z and minus N tests in your conditionals. So minus Z means zero length and minus N means not zero length. So if you want to check, is there a limit? Then you can just say if minus N, dollar one or dollar limit. And if you want to check if there is no limit, then you use minus Z. Because if the limit is Z or zero, nothingness, then there is no limit. So depending on which is easier to write your code, which will make the most human friendly code because you've got all those used not, of course, to switch everything around. But I like to write my code so that I can say it and it's written the way I would say it. It just, it makes code easier to maintain. So you're comfortable saying minus Z as a human word? Yeah, because if my brain is like empty, right? If the limit is empty, if the limit is not empty. Yeah, I'm just barely getting to where when I see minus Z, I don't go, what the heck is that? So I'm definitely not at the that looks like a human friendly thing yet. I'm getting there. I guess it's looking like isn't quite right, but logically being structured as. It's easier to read. It says if the limit is empty, it's easier to say than if the limit is not, not empty. I mean, if you end up writing your code with knots and stuff all over the place, when you're saying it, it's like not, not, not, or not. But it's actually the other way around. It's if empty limit. But depends on what you're trying to do. It's not if limit is empty. I think you may be digging more deeply than I'm intending you to. You can end up writing your code with knots and stuff, or you can write your code where you're at least having the operator that makes it the straightest path so that you don't tie yourself into big circles trying to debug your code later. If you can write, if you can avoid writing if not this or that and all these, like if you can make your conditions as simple to express as possible, in the future, you will be thankful because you will tie yourself in knots. I guess that's the point I was trying to make. But there's an infinity of ways of doing it. And then the only very small other subtlety is, what did I say? Actually, no, that's it. That kind of is all I figured I could even say. It's all very by the book, very by the book. Good. Okay, so that then brings us on to our friends, these special POSIX variables because we've already actually seen some of these. So I've written up a table in the show notes of the most commonly used of these. The first one is dollar path in all caps. That's part of the POSIX standard. So the path is a list of directories that your terminal goes and searches for when you hit a command. So when you type the command git, where does it go to find git? It checks everything in the path. Dollar home will always be your home directory. So in bash, we can use tilde, but that's a bash thing. In any shell script that's POSIX compliant, you can use dollar home. That is a POSIX thing. So let me back you up a little bit. We're calling those variables. We were talking about POSIX standards when you started. So when you say a variable, you mean it's a standard existing variable that I can always use everywhere in any shell script or at the command line and everybody knows what it means? If your shell is POSIX compliant, it must provide these variables. These variables are mandated by the standard. You mean match these variables. These variables must mean this. Like, dollar home must mean the correct user sum directly. Yeah, so the specification says you must make these variables and they must do this. Okay, okay. So that means that whether you're in SH or bash or in Linux or in UNIX or anywhere that's POSIX, you can use dollar path and it will be where are the executables hiding? They're somewhere in your path. Where is my home folder? It's in dollar home. Again, bash people can take a short cut with the tilde character, but that's a bash thing. The other one then is the input field separator or dollar ifs and you have encountered this strange beast and I have warned you away from it because this little fella subtly affects how other terminal commands work by effectively changing the definition of what is a space. Basically what it does. And if you set ifs to a non-standard value at the top of your script, then 100 lines later, something could utterly break because it will have switched from defaulting to I split on spaces to, oh actually I split on tildes now or the other common one is you'll see terrible code for I wanna process a CSV file, change ifs to comma. Great, that one line of code will now work. You will now be breaking apart your CSV on commas but the read line later down your file has just gone completely nuts because instead of breaking at the end of a line it's now breaking whenever the author puts a comma in the text. But warning me off of it seems like an odd thing because I mean there was a better solution to my problem. What I was doing was I was telling it don't make ifs be a space because just for a minute here because I need these things to be stay together and not get separated my more and my bacon needed to stay together and I was immediately turning it back off right afterwards and that was a, sounds like what it's for. And by the way the internet says to use it. No, there are people on the internet who are wrong about many things. The internet tells you all sorts of terrible things. It's a pretty common answer to the question because I kept searching and searching and searching I kept coming up with that answer every time and if you use it and then you undo it if you put it right back to space like if you wrap your you have to remember to do that or you have to put it inside the soap shell where it's effect is contained. It's like a radioactive source. They can be safely used but you do need to know that it is a radioactive source and that it does have side effects. Mark Watney, whatever you do don't dig up this radioactive source. Right, exactly it is like and especially when I know that the answer is just to quote the thing. It's like don't go near the radioactive source. But that took me three weeks. Right, I know, but I didn't want to say yes, Alison you have found the answer because I really wanted you to find the quoting solution because that is actually the better answer by far. You know, don't break it. Don't get me out of the bars for weeks. So it was a good thing. There we go. Now I think we will cover we will probably look at it later when we have looked in more detail at soap shells because that is there's a special keyword in Bash called local that basically says I want to shrink the scope of my actions so the dearest, tiniest thing possible and local and ifs are very good friends because they avoid spooky action at a distance by basically saying make my spooky action right here and then you can use it because you've basically led shielded it. We're making this analogy far too we're stretching it out, but you get the idea. We've also seen the next of the special variables dollar question mark it is the exit code from the previously executed command. So we use dollar question mark to see what was the exit code of the last command. If you say echo dollar question mark you will see the zero or the one from whatever came before. Oh, that's right. Well, we haven't seen before but you will find that on the Google's quite a lot is dollar dollar, which is basically my process ID. So if you need your scripts to find out what process is running as it will be dollar dollar. If your script starts another script as a background process with the ampersand symbol and you may want to then kill that background script you started before it finishes because you've decided if it runs for more than 30 seconds something's gone wrong. How do I get to it? Well, it's ID will be in dollar exclamation point. So you can then say kill all dollar or kill minus kill dollar exclamation point. But your notes say it's the most recently started background task. I could have had my backup start running and be the most recently started background task. No, cause it wouldn't be started by you. All of this is from the point if you have the script, right? So if it says for your script dollar question mark is for what's in your script, right? It's local to you. It's not system-wide. Cause otherwise it would, yeah, otherwise it would be potluck. Seriously potluck. That would be spooky action at the distance of a very different kind. So if your script starts something with the ampersand symbol, so you've backgrounded it, then you want to be able to kill it. But if you background five things and you don't save the value of dollar exclamation point into a variable of your own, you have lost at the next time you use the ampersand to background something else. Taking the terminal, we looked at backgrounding with ampersand. It's not something we've done here because we have never had to write a script that we want to do two things at once. Cause that is how you do multitasking in the one script, right? You could have the one script start. Oh, so many ways of like code running in parallel. That's what's worse than radioactive. That is how you get bugs. That is how you break things. That's how you get race conditions. That's how security falls apart and is handled with great care, that one. We already met dollar one to dollar nine as the positional arguments, but they have a very logical friend, dollar zero. It's the name of the script itself. So on the terminal, you type- Does that include the path? Does it include the path? I don't know. It's exactly what you typed in the terminal. So if you type dot slash, then dollar zero will contain dot slash. If you typed the full path, then dollar zero will contain the full path. It's literally, whatever you typed before the first argument is the zeroth argument. It's how was I invoked? Okay. It's potentially useful. Also potentially dangerous, but not dangerous, potentially misleading, potentially not as useful as you'd hope. Usually potentially not as useful as you'd hope, actually. And then we come on to the three I really care about for today. Dollar, octo-thorpe, pound, hash, whatever we're calling it this week. Dollar star and dollar at. And they are all to do with our arguments. They tell us things about our arguments. The first one is the very easiest one. How many arguments are there? That is stored in dollar, octo-thorpe, dollar, pound, dollar, hash, dollar, shabang, I think that's some of the names we use. Dollar, hash. Didn't we decide on dollar, hash? Dollar, hash. The one with the two lines and the other two lines. So if you wanna know, did they pass four arguments if open square bracket, open square bracket, dollar, pound, minus EQ four, they passed four arguments. It's a number. It's very straightforward. I have written a demo script. Should you feel like it? PBS 149A num arg is at SH. It says echo you passed dollar, octo-thorpe, args. So if you run that script and you pass it no args, it'll say zero. If you run that script and you pass it say 42 as one arg and then space, single quote, life, universe, everything, single quote, it will correctly determine that it's two arguments even though they have spaces because you quoted it. Leave the quotes out. It'll tell you you passed four. It's very straightforward. And then we get to our two friends. And our two friends, these are the guys I warned you about that don't know if they're a variable or an array. They don't really know what they are. Officially they're called expansions. So they behave more like star.txt than anything else. They will expand out to become the arguments of the script, but they will do so in subtly different ways. And you can make dollar star behave not just subtly different, but dramatically different by messing around with ifs. Because ifs will actually control how dollar star behaves. So by default dollar star breaks everything apart on spaces, but if you make ifs be something else and dollar star will break it apart on something else. It's actually really difficult to explain in English how they're different. So I have written a script so I can show you how they're different. Let me guess you had to do this to get it straight in your head too. I tried to read it and then I tried to understand it and then I tried to replicate it and I was like, nope, I'm just gonna do a script. So you will find a pbs149b-rxexpansions.sh and what it does is it echoes just to show how many arguments are really or are you past dollar octosorp rx, great. Then it runs a for loop across dollar star with no quotes. So it's an unquoted version of dollar star. Then it runs a loop over- Wait, wait, wait, stop, stop. A in dollar star. I don't have any, you're saying for whatever in this expansion variable. But I don't know what that means. Well, I'm gonna show you when you run the script, you're gonna see what it means. Dollar star expands out to represent your arguments in a certain way and you will see what it does when we run it. But you're acting like dollar star is an array. Correct, you're asking an array like question so it's behaving like one. Okay. I told you they're weird. It expands out to become the arguments and you will see how it does the expansion when we run this code. It will produce a number of items that the for loop is going to loop over and we're just gonna print them out. Okay. So it's for for loops. What happens if I expand dollar star without quoting it? What happens if I expand dollar at without quoting it? What happens if I expand dollar star with quotes and what happens if I expand dollar at with quotes? What do you mean with and without quotes? Okay. So you can see it says for a in dollar star, no quotes. Then we have for a in dollar at no quotes. Then we have for a in quote, dollar star quote. That is a quoted dollar star. And then we have for a in quote, dollar at quote. Okay. So like you can quote any variable, you can quote these weirdo variables and if you quote them or don't quote them, they will behave differently if they contain spaces. So if you have arguments with spaces, there are four possible things that can happen. And rather than try explain it, which is impossible, we're going to run this code with different, are you? Oh, great. I pasted the code twice on the results. I think you've got the results in there, but I've been sitting there looking at that. That was part of why I was super confused because he's got the code twice. I've got the code twice. Oh, few. I've only got the code in twice. Right, but I think the other part's fine. The other part is fine. I thought I'd left out the other part and that would have really ruined this description. We're going to run, I see what's missing. What's missing is the bit where I say, run the code with name of script and then the two arguments are 42 and then inside single quotes, life, space, universe, space, everything. So that's what's missing there. I will fix the show. You see why I was a little stuck. I get the way you're really confused. All right, so we're gonna run this script with two arguments. So we're gonna say dot slash the name of the script, space, 42, space, life, the universe and everything, not in quotes. No, we're gonna quote the argument. We're gonna quote the argument so that we have a normal argument which is 42. Exactly, exactly so one. And we're gonna normal argument which is 42 and then we wanna quote it argument which is life, universe, everything. I didn't bother with the and. I figured you'd get the joke. Okay, I'm gonna do it but I'll just do it with something a little bit easier just so I can follow along. Life, the universe, I'll just stop right there. Yeah, so you will notice if you don't quote them, they behave the same, right? Unquote a dollar star becomes four things. 42, life, universe, everything. So because we didn't quote it the spaces are all, you know, as far as the for loop is concerned the spaces are there so the for loop sees four things because we didn't quote it. So could I remember that as a dollar star without the quotes doesn't keep that array as just two entries, it breaks it up at the spaces. Yes, and dollar art was exactly the same thing. Okay, that kind of helps me remember it at least. I didn't have quotes around it so it did look at it in a separate things. It broke apart, okay. Now, if you're an advanced programmer, you can use ifs to make dollar star exploded on something else so you could make it split on every I by setting dollar ifs to I and then you're gonna get like 42 L and then- No, we can't let Allison play with the ifs. That's dangerous. Yeah, precise, right? And whereas dollar art will ignore ifs, dollar art will just do the spaces. So dollar art is your reliable I will break it on spaces. It's very straightforward. But then the question is, what happens if we quote it? Well, dollar star takes everything and says, oh, you want it all in quotes, do you? All right then, one giant big thing, 42 space, life space, universe space, everything. It quotes the lot. Oh, okay, okay. So it takes the two arguments, slaps them together, put spaces everywhere and says, great. Or you could think about it as star for all. It's all arguments as one string. Yeah, interesting. Dollar art, when you quote it says, well, I'm going to give these back like they were given to me. I got two things. I will give you back two things. So quoting dollar art is 99.999% of the time what you actually want it. I was just about to say, I'm not learning any of the other ones, Bart. I'm only learning that one. So what you want is double quote, dollar art close to the double quote and that will give you your arguments, like a sane person. I would like them the way the user wanted them. Hey, how about we do what the user asked? I'm sure there are valid reasons for mushing them all together. Yeah, cause a dollar star quoted seems vaguely useful. Give me everything just in one big string, okay. But unquoted, they're both pretty useless in my opinion. Right, now these things are behaving sort of kind of like arrays. Could you have an actual real array please? Well, thankfully you can because you can combine the quoted version of dollar at with the array syntax and just making you array named args by saying args becomes equal to open around bracket, quote, dollar a close the quote, close the round bracket. Ta-da, a normal array named args that contains your arguments. Okay, you like to do that just cause it's human readable now? Like it makes sense to you. It means that I can then, yeah, so if you have a thing where you by default you do one thing, otherwise you do whatever was in the arguments where you're gonna have an array that you're gonna default to some stuff or what do you do afterwards? You could have an if statement that says if it was an array, you write this code, else write this other weirdo code with those expansions or you could turn the expansion into an array and just do the same thing. Or if you want to add some default values before and after the arguments, right? Sometimes it's nice to have a real array. They can do things with real arrays, right? Not something just masquerading as an array? Not some sort of quantum mechanical thing that doesn't know whether it's up or down. So yeah, if you want a real array and you'll see that a lot on results, you'll see open round bracket quoted dollar at and what it's doing is just saying give me an array, no messing about, just give me a real array and it makes everything easier. Okay, so there is an example in the show notes which proves to you that it is just an array and it uses all the same syntax we use in the previous installments with the dollar, open curly bracket, octosorp, args, open square bracket at close square bracket to give us the number of items in the array and we can loop over it by having the quoted dollar, open curly bracket, arg square bracket at close square bracket, all of that syntax you hated. It all works fine with this new array we've made. You know, I don't actually hate it because I've gotten used to thinking it through each time. It's certainly not native. I think it's through as well. Look how it's in quotes, Bart. You always usually want to quote things. This is probably the thing I will never forget is I'm gonna, well, everything's gonna be in quotes whether it's right or wrong from now on. But if you think about it this way, quoting by default is safe. Yeah, yeah, it seems like it. Yeah, pretty much, because then spaces don't break everything. Yeah. Right, so all of this is in preparation for the main event of the day. So this allows us to deal with normal arguments, right? Like, you know, space 42, some string or whatever. But remember I said that we want it to be like those big boy terminal commands, right? Like LS. And what do we know about LS? Well, it does things like LS minus L. Or you can specify funny colors with minus color or minus C for the different colors. You can do all sorts of cool things. Like our terminal commands have these minus blah flags all over the place. How do they do that? Well, they could do it in an infinity number of ways, but it's become a sort of a pseudo standard. And the way they do it is with the SH and Bash both do it with a built in feature of the language called get ops. And we're going to learn how to do that. Now, I'm going to give you a little warning. If you go Googling for get ops, you may get sent down the garden path because there's a completely different thing that works completely differently called get opt without the S. And that is a terminal command, not a bash language feature. It is a very old terminal command that predates bash and could be argued has features get ops doesn't, but is so complicated it may as well have no features because you'll just go insane. It will just break you. So get ops S, the S is for super or whatever. I don't know, plural is better, more is better. Anyway, get ops. You want to be careful you're looking for the documentation for get ops with the S on the end. So when you look around at the terminal, there are actually two distinct, okay, so the universal term in the jargon for these minus blah things are options. And options come in two flavors. You have a Boolean option, basically it's there or it isn't. And we euphemistically call those flags because like a flag on a mast there either is a flag or there isn't. So there either is a minus L or there isn't. Oh, so that's why that's why they're considered Boolean? Yeah, they're either there or they're not. Yes, no, in this case, present absent. And they're referred to colloquially as flags. So you just flag the fact that. Boolean options sounds funny. Boolean to me is and or or, right? Well, Boolean means two valued. So Boolean, so decibel means 10 valued. We happen to use the symbols one, two, three, four, zero, one, two, three, four, five, six, seven, eight, nine. It could be donkey, banana, pear, whatever. As long as there's 10 of them, it's decimal. Boolean is on, off, true, false, yes, no, one, zero. They're all Boolean. They're common pairs and they obey Boolean algebra. They're Boolean. But the meaning of them is yes, no. What you say when you use the word Boolean and. That's what it is here too, right? Either the flag is here or it isn't. Does it do it or don't? Well, yeah, but the variable is here or it isn't. It's not called a Boolean variable. The argument, if you're giving an argument to a script doesn't, and it's optional, doesn't make it a Boolean argument. It's just an argument. I very like it. Informal computer science. Informal computer science, it is absolutely a Boolean because the flag is either there or not. That is Boolean, true, false. Did they specify minus L? Did they not? The minus L is there or not. The minus L is present or absent. So there's a test running to see if it's there or not. It's true of any Boolean variable. Yes. You don't use a Boolean. That's what I'm trying. No, I'm trying to back into why it's a Boolean option is because there's something that's gonna look to see is there a flag or not. It has to either, it has to be a one or a zero. Okay. Yeah, it's either there or there or not. Okay. Okay. In contrast, an optional argument is minus some letter space a value. So the SSH command will assume you want port 22. What if you don't? You say minus P space 2222 if you wanna go to port 2222, which is the default alternative. So the minus P says, I'm going to tell you in the next argument, I want a different port. Next argument, the different port. Interesting. So optional arguments always require a value. I never noticed that. That's what makes them different. So that is what defines being an optional argument versus a flag. If I need a value, I'm an optional argument. If I'm just there or not, then I'm a flag. Okay. So do I need a piece of paper or am I just a thing I stick up in the air or I don't stick up in the air? Okay. I think I'm with you. Okay. It's actually hard to say in words. It's kind of more logical looking. So just to remind us, if you don't taming the terminal, you've seen a lot of flag type arguments, right? So the one I always go back to by default is LS because everyone knows to type LS minus L. If you don't type- I'm going to tell people something really quickly. If you're new to this series, taming the terminal is another podcast that Bart and I did. It's 42, I don't know. I think 43. 43, which makes me slightly sad because it's not Douglas Adamsy. Shouldn't have done that. But anyway, it's a podcast about, in the mid 40s of episodes teaching how to use the terminal, in case you haven't, that's what he's referring to. Okay. So go back to minus L. Yeah. So the LS command by default gives you a multi-column list of files, right? If your directory has 10 files, it will list a few of them and then a space and then a few of them and then a space and then a few of them. Parallel columns. If you want to see the details, you want a listing and the way you tell LS, turn on your listing mode is with the minus L flag. So you just say LS space minus L and then it outputs this nice details listing instead of the columns. There's another flag minus A, which tells LS that you want to see all files, even the hidden ones. So what you've probably also seen is LS minus AL. That's called cuddling your flags. And it literally is the same as LS minus A space minus L. Okay. And getups implements this convention. So with getups, we can cuddle our flags. So there we go. Getups, let's us do that. Okay. Why is minus L not the default? Who ever wants to see it in those annoying columns? I mean, if there's like three things, maybe. I have one minus three. I can't read it. I never use LS without minus one or minus L. So minus one puts them all under each other without the detail, which is great if you're putting the result of LS as a pipe into another command. If you want to count something, you can, you know, it's a nice way to count things. Or if you want to grep for all files that look like something, or I want to see the details. So I either want LS minus one or LS minus L. A plain old LS is just annoying. You can't copy and paste it. What do you do with it? I can't even read it. Rant over. Exactly. Poorly. Yeah. Oh, God, yeah. Yeah, terrible. Okay. So to illustrate the optional args, the most common example is your minus P for the port number on say SSH. So SSH space minus P space 2222, some user at some dot server. The important thing now, there are people who will tell you that minus P is a flag. Those people don't actually understand what a flag is. That is not a flag, it is an optional argument. Yes. Yes, because it requires a value. The 2222. And it makes no sense, right? I mean, I want a custom port. If you don't tell the custom port, that is nonsense, right? What is the point in raising a flag to say, I want to do something different and then fail to tell poor SSH what the something is. It doesn't make sense. So there are logically different concepts. And so it will be obvious to you what you need. Now, there are some limitations to get off, to get off is old. It actually comes from the born shell from SH. So there's another convention that has come up because terminal commands have gotten complicated. So there are 52 possible flags slash optional arguments with this minus whatever scheme. There's minus A to Z and minus capital A to Z and then you're out, right? Oh, good point. So you can have archive and add with minus little A and minus big A, but what if you want archive, add and append? You're gonna have to call one of them minus P for app end. Or something, right? You start doing these weird things like grep uses minus V for invert because minus R is needed for case insensitive. You just use minus one. Okay, that's fair point. That's true, that's true. You do also get minus. Well, no, can you have those? No, you can have those. You're right, you're right. You can have those. Okay, so 62. But the point being, when you try to make them have logical, memorable names, you run out. And so there's a new convention called long options, which is minus minus and then a name name. And get off does not do long options. So we are stuck in the past. So we can't have minus, minus track like we can use in bash or not in git, right? We'd have to use minus uppercase T or something. The other thing that get offs is very limited on get offs doesn't let you mix things, right? So you can, when you use LS minus AL, you still give it a normal argument, which is what would you like me to list? So if you leave it blank, it'll list the current directory, but you can list any other directory from anywhere. If you say LS minus AL tilde, it will list your home directory no matter where you are. And I'm pretty sure LS is smart enough that if you say LS tilde and then minus AL, it will still be happy. And there are many terminal commands like with SSH, it won't care if you do the minus P at the beginning of the end. You can say SSH user at server minus P443 or SSH minus P443 user at server, it doesn't care. Mix them and match them, it doesn't care. Get ups is nowhere near that forgiving. First come the options, then come the arguments. Can't mix them. So you have to do minus whatever, minus whatever, minus whatever, and then the regular arguments. It's not a huge problem. It's just a little bit less flexible. So the user has to do it in the right order. Okay, just fine. Okay, so now I spent so long trying to write this bit of the show notes. Get ups is really simple and it does make sense, but I think you need to be on mind altering drugs to notice. So it is designed to be used in a loop. So what get ups does is it starts at the start of your list of arguments and it does one flag. It saves some information in some variables and then it exits with an exit code. The exit code is success if it's not finished and it would like to do another argument at some, when you feel like it or failure when it's finished. In other words, it's designed to go in a while loop. So you will always see while get ups. You just lost me. I'm gonna be using get ups as a, in while loops? I thought get ups was the name for this description you've been giving us this whole time of using flags and optional arguments. It is a command that will process those flags for you. So your script will be designed to accept flags. You need to write code to react to those flags, to process those arguments. Those flags are just arguments. Your script has been called with arguments. Some of those arguments have a name starting with a minus, which makes them an option. I think I'm lost at the very beginning still, Bart. I thought get ups, like I said, I thought you were describing get ups was this collection of this concept of optional arguments and flags. But you're saying I'm gonna use get ups to use those terminal commands inside of my code, my script. No, so that your script can accept flags of your choice. So if you are writing a script and you want your script to be able to have a minus V for verbose, then you use dollar one to get the first argument and you use dollar two to get the second argument. So that's how your script reacts to arguments. But how do you react to options? So how do you react to these special arguments that start with a minus? You could write your own code. How are the special arguments gonna get into my code? Okay, so you could write your own code to loop through every argument, check if it starts with a minus symbol, and then you do all of the work of figuring out that it's one of these options. But I must have written my shell script to want to see a minus V. Right, exactly. What you would have to do all the work of figuring out is this a minus V, like there's a lot of processing because if you say my script to minus V, some arguments, well, the minus V is optional. So sometimes some arguments is in third place and sometimes it's in second place or whatever, right? Yeah. So dealing with that complexity would involve a lot of code. You could do it from first principles and you would end up writing lots and lots of code that you would then have to replicate in every script you write. So getOpts does it for you. GetOpts understands these minus style options. GetOpts does the heavy lifting. In a concise sentence, getOpts allows you to take in arguments that have flags or optional arguments. Yes. There. It processes them for you. Now I know why we're talking about getOpts. I did not get that at all. Okay. So it is the chainsaw for cutting that particular plank of wood. It is the tool you will use to help you do that task. And it does it one at a time. So it starts at the start of the list of arguments and it looks to see are you a flag? Oh, you are a flag. I will capture your details and I will store them and then I will stop. And I will also check to see if there's another one to come. If there's another one to come, I will exit with success. If I'm finished, there are no more flags, sorry, there are no more options. Then I will exit with fail, which means that in a loop, as long as there's more work to be done, the loop will go round and round and round because the loop will keep going till it gets a fail. So this is how read line works, right? It's give me a line and I will exit with success or fail depending on whether there's another line to come. So I will exit with success or fail depending on whether there's another option to come. And so you will always see while get opts because otherwise you're just gonna get the first option and that'll be that. So you're gonna loop them. Now I've done a bit of hand waving there. It puts some stuff in some variables. I may need to make that jump a little bit higher at you. So it actually uses three variables and one of them, it lets you name yourself and usually letting you name things yourself makes your life easier. But in this case it probably makes life more confusing because it means everyone's example on the internet is different because everyone has picked a different name. So the first argument that can have any name you like, I am always going to call it opt because what get opt does is it puts the letter of the option that it found into this variable. So if it found a minus V, the variable of your choosing will contain the value V. If it found a minus D, the variable of your choosing will contain the letter D. If it found a minus H, it will contain H. Okay. Am I making sense? Yeah, I don't, not yet. How we're ever gonna use this, but. That is a worked example on the way because that is the only way to make this make sense. But I do need to, I do need to say it, confuse the crowd by the view and then we can unconfuse you with an example. Okay, so we're just gonna use opt as our variable name, but we could use it, it could be pancakes. It could be pancakes or waffles or anything we like, exactly. But it will contain the option we found, right? So get opt goes and it looks to see, is there an option here? And if there is an option, it will put the name of the option into the variable of your choosing. It will also fill or not fill the magic variable opt arg in all caps. Cause if it's a minus P port number, where does the port number go? If it's an optional argument, then the value of the argument goes into opt arg. So it's always opt arg, but it's not always opt arg. It's always opt arg. Yeah, exactly. Why like either pick them all for us or pick none of them for us. This is the, this I don't get. Okay. Now I said that it steps forward step by step by step. How does it know where it left off? The next time it comes around the while loop, how does it know where it was? It uses the variable opt ind, which is the index of where it is in the list of arguments. And that's really useful because when it's finished, it tells us where the dividing line is between the minus stuff and the normal arguments. So depending on how many minuses there were, the normal arguments are going to be in different places. So dollar one isn't dollar one. So we need to actually, when we're done dealing with the minuses, we need to clean house so that all the other stuff is available to us as dollar one, two, three, four, et cetera. And we can do that. But only because opt ind will tell us how much Detroit us we have to clean away. So if I've said LS minus AL in there, it would have opt ind would be two. Or let me guess, one? Correct. It starts at zero? Of course it does. No, no, not because it starts at zero. If you think about it from the terminal point of view, minus AL is one argument, minus AL. Now opt arg understands that that's two options. So it will go around its loop twice, but the value opt ind will be two because the next thing is the second argument. So opt ind always points at what's next. What would I look at next? I would look at the thing after what I've already processed. So opt ind is always one in the future. Don't worry, there's a copy paste one liner that does all the cleanup. Like all the cleanup is a copy paste. But the point is opt ind makes it possible to tell the difference between the minusy stuff and the other stuff. Because we need to get our other stuff, right? We can't lose the other stuff because then we suddenly lost an amazing ability to just have plain old arguments, right? The easy stuff would become impossible, which would be so silly. Like we can have these weird arguments, but no normal ones, I don't want that. So anyway, we have our three variables. Now, what arguments does get opts want? So get opts is effectively a terminal command. So while get opts, get opts what? The first thing you have to do is you have to tell get opts what flags and optional arguments you are expecting or are valid. And you do that with a string. And because they're all one letter names, you just put the names you want in the string. So if you want to accept a minus A and a minus B, you just put in the string AB. And they will be two flags, A and B. So if you want A, B, not A space. Just A, B. No, just A, B. Okay, well, I'd like that works because you would know it's always going to be one letter. So it chops it at every letter. Exactly, precisely. If you would like A to be an optional argument, it's A colon. If you would like B to be an optional argument is B colon. So the colon after the letter just means it means it's like a minus P 443. Okay. So no colon flag with colon, I want to value. So A colon, it's waiting for the thing on the other side of the colon. Okay, all right. That's how it knows whether I take one argument or two. How big of a byte am I supposed to take here? If I see minus P, get opts needs to know it needs the next argument too. Right, if I see a minus L to LS, it knows I'm done. This one doesn't have any more, I'm done. I can go on and do the next thing. So that is how you specify it. And then you will, if you ever invent the time machine I promise you you're going to use it to go back to the developers of get up. Because A, you're already cranky after for making you name one variable, but not the other two. And B, you're going to kill them for reusing the colon for a completely different meaning in the same string. Oh, come on. I'm not making this up. I couldn't invent a dumber thing. If the colon goes first, it means I'll write the error messages. Thank you very much, not you. By default, get ups will put very, very generic error messages that are of no assistance to anyone. If you would like to have an actual error message that means something, you want to write the error message yourself. And the way you tell get ups to be quiet is by starting the string with a colon. So before you put any letters in, you put a colon in that basically says, shh. And then you put your letters in. So colon A colon would be an optional argument where I'm going to write the error message. Yeah. And colon A without the second colon means a flag. I know I'm going to write the error message. So do you write the error messages by flags and optional arguments? So would you end up like colon A colon B colon? No, because the first colon is either present or absent. So either the string doesn't start with a colon. And after that it's letter optionally followed by a colon letter optionally followed by a colon letter optionally followed by a colon. So it could be A, it could be colon A colon B C colon D. And that would mean two of those who had optional arguments and I'm going to write all the error messages. Yeah. Wow, okay. Yeah, that leading colon is just the, that has go down in history as one of the silliest decisions that a human being has ever made. Cause it makes the whole thing really hard to read. Like really hard to read. Okay, so the first argument to get ups is this string that tells it what flags, what options, whether they be flags or optional arguments, what are we expecting? If you use a flag or an optional argument you haven't defined, then it will actually come to you as question mark. So remember I was saying that you name a variable and then that variable will contain whether you did a minus A or a minus B. If you tell opt arcs that you only want a minus A or a minus B and someone gives you a minus C, they won't get C in the variable, they'll get question mark. If you give anything that wasn't supposed to be there, you get question mark and that's how you know to shout at people. Oh, if question mark, you did this wrong? Yes. Yes. So basically who? So get up to this kind of like, I like to kind of like the idea of get up going, what, I was told to look for this and this and you get what? Right, so question mark. Okay, so the second argument to get up is the name of that variable that you have to give a name to. So we're always going to say, get up to some string with some colons in it, opt. Okay. So we're always going to do that. So we're going to have while get up, a string opt. So what do we do inside the while loop? What inside the while loop, the value of opt will be whatever the letter of the flag that was found. So it's processing your arguments, looking for flags. The first time you go into the loop, get opt finds a flag. It will put the letter into the variable you gave it, which is dollar opt for us. So we have to check what is the current value of dollar opt? And then we have to react to it. Now you're on mute, by the way. I certainly am. I've been saying. Fine. I can lip read really well. I can lip read really well. It really wasn't a problem, but I figured it would become a problem. At some point it might be. So this is why we do video. So we then, we could do a bunch of if statements, right? If dollar opt EQ A, else if, dollar opt EQ B, else if, which would work perfectly. However, it is really messy code. So remember we learned about the case statement a few installments ago, which is basically a really efficient way of doing an if else. Yeah. That is why every example on the internet will be while opt, while get opt case. Those three commands go together, like love marriage and something, kids I guess. So you will always see that particular structure while get opts case. And then inside the case statement is where you deal with your flags and optional arguments. So this is all very hand waving. So I'm going to stop waving my hands and they're going to show you some code. So we're going to write a script, which is going to take two options, a flag and an optional argument. So this is hello world, but we're giving it a spin. So the flag you can give it is an Allison friendly flag, minus S for B snarky. Okay. And the optional argument is an adjective to describe the world. So hello, what world? Wonderful world, wicked world, wobbly world, wibbly, wobbly, timey, wimey world, right? You get this put an adjective in front of world. And that is the optional argument. So that gives us minus S for whether or not to be snarky, which is a flag. So there either is or there isn't a minus S or minus W and then your world adjective. Okay. I'm looking at your code and it does, I don't see how we know that's a minus W. Okay. Well, we will get there. So what it says is B snarky equals quote, and he says, assume minus S is not passed. So wouldn't it be snarky? Right. So we need to set some defaults for ourselves before we actually process the arcs, right? So the first thing we do in our script is we set up the default behavior. What do we do if they don't pass us an option? So I'm going to start by saying B snarky is set to off, which I'm just representing as B snarky is empty. Right. So my code basically assumes it starts, it's starting assumption in life before it checks its arguments is not to be snarky. It's starting assumption before it goes and checks its arcs is that the adjective will be wonderful. Okay. Then we use get ups to figure out what the user actually asked us. Okay. Right. So then we say while get ups and then the string we use is colon SW colon. Okay. So let me, let me say this. We put it in quotes because it's a string and it has funny characters. So let's just quote it to keep it safe. Sounds good. Okay. And there's a colon at the front because that means I'm going to write my error messages and we've, we've got two flags S and W. Actually, I'm sorry. Hang on. Let me say, let me say don't catch it. S W colon means that S is a flag and W colon means it's an optional argument. Bing, bing, bing. And we're going to put it into opt. We don't put it into dollar opt because we call it dollar opt later. It's opt here because we're defining it. Precisely. So we're saying it will be opt and we get the value of opt with the dollar operator, which is give me the value of. Right. Okay. Right. So while get up, our string opt, do. First thing on our key. Be clear and say get ups. Because I've been, I've been hearing get up. Yeah. I'm afraid we should do a command F in the show notes for get up because I'm sure I type it somewhere. I did my absolute darned us not to, but you know me and there's a good chance of at least one. Anyway, I don't, I don't see any. Yay. Go me. There's probably one somewhere that's, there should be one somewhere that says, don't use the wrong one. There should be a match of one anyway. So then inside the first thing and the only thing inside our while loop is the case statement. So that goes from case to ESAC, which is case backwards. We snarked it at that last time. So case dollar opt in. So in other words, we're saying we want to look at every possible value or we want to look at the different values of dollar opt. And then we say the first value we're interested in is S. If we found an S. So everything between the S bracket and the two semicolons is what happens if dollar opt contains S. Okay. I'm forgetting this syntax because case was not last week. It was quite a while ago. It says S, roundy bracket and ends in double semicolons. Yes. So between the two. And that's the normal case context. That's the normal case syntax. Okay. That is the very weird normal case syntax. It means that everything from the bracket to the two semicolons is what we do if it's an S. So we have dollar opts. It's very clean. That's why it was written this way. Yeah, exactly. I always have to go look it up because it's a bit weird, but it is very clean. So if at any point to the loop, we meet the S flag, what do we do? Well, just to make it clear what we're doing, I am echoing a debug statement. In the real world, you would not echo a debug statement. So I'm just saying echo debug enabling snark. And then I'm doing the actual work, B snarky becomes equal to one. And so they gave the minus S, therefore we shall be snarky. Okay. And that was the variable that you defined upfront. Correct. That you set to a default value of not snarky, which that's a little weird, but okay. Yeah, I hummed and hollered, but anyway. Then we have the case for W. So W bracket as far as the two semicolons. So what do we do if it's a W? Well, again, we have a debug statement saving the custom adjective, dollar optarge, right? Because optarge, we didn't get to name it. We'll always, the value for an optional argument will always be an optarge. So what do we do? Well, we have to save it because the next time we're in the loop, optarge will have a different value. So we say world adjective, yeah, world adjective becomes equal to optarge. And we quote it because what if they put a space in? Very valid to have, you know, wibbly, wobbly, timey, wimey world, right? That is sort of an adjective. And then we need to check for question mark because question mark is get up to a way of saying they, it wasn't an S, it wasn't a W, but it was a minus. So we have to have a case for whew. So there is a, basically, you'll notice Linux and Unix commands do this. They say usage colon and then they print out the name of the command and then they list which arguments there are in square brackets if they're optional. Now, we could write the name of the script, but it's way nicer to show you the dollar zero and use in combination with the base name command we learned about in the previous install month that takes away everything apart from the file name. So dot slash whatever becomes just whatever or slash whatever, whatever, whatever, dot, you know, basically becomes just the file. Everything before the name of the file gets thrown away with base name. And the file in this case is the name of the shell script? It's whatever you typed to run the shell script. So if you type dot slash the name of the script, then it will be dot slash the name of the script, but base name will take the dot slash away. If you typed slash home, slash Allison, slash document, slash. Right, right, okay. Got it, got it. Yeah, no. Dollar zero will contain it all and base name will clean it up for you and leave it at just the file name. Okay. So basically then give me my file name and then minus s, minus w, adjective. Got you. Let me say that one more time. So dollar zero is whatever you typed in, which may have been the full path and base name is just gonna grab the base name. Including the file extension, right? Yes. Okay. So everything that's not a folder. Okay. So there we are. And then we just, oh yeah, exit one. Yeah, because when you get an error, you really should shut off. Yeah, exactly. And then we end the escape, sorry, we end the case with an esac and then we end the while loop with a done. So what do we do? Okay, so that's, we have now processed our arguments, right? That went, that took zero amount of time should the loop, if they gave us no minuses, if they gave us both a minus s and a minus w, then we took two goes around the loop. And if they gave us something weird, goodness knows how many, well, at least one extra time around the loop at most because then we would have hit the exit one and saw it off. Right. So that loop will have happened a number of times, which means we will have dealt with our different options. So now we're ready to actually do our greeting. So I'm gonna assemble the greeting in the variable named greeting. I'm gonna start with an empty string and then I'm gonna say if B snarky is empty, sorry, if B snarky is not empty, then the greeting is, oh, yo, otherwise, the greeting is, hello, I was trying to be snarky without swearing, oh, you, of course. So minus n is not? Minus n is not empty. So if B snarky is not empty, then we shall be snarky. So oh, yo, otherwise, hello. And then we say the greeting is plus equals, space, dollar, word, adjective, space, world. And then the exclamation point is in a separate little string because otherwise it will break everything because you can't have an exclamation point in a double quoted string because it has a meaning. As we've discovered quite a few times in this series. And then we echo. Plus equals, why is it greeting plus equals or you? In quotes. Well, because I'm building it up, right? I started with an empty string and I'm building it up yet. Okay, so the first ones we could get away with just equals because the string was empty, but it's a really good habit to build it up because what if we want to prefix it with like an emoji or something in the future? Okay. This way my code is robust. Okay. I always write like this. I didn't catch that you were building it up, okay. Yeah, so we start by saying greeting is an empty string and then we build it up with the snark and then we finish it out by adding in the adjective followed by world, followed by the exclamation point and then we echo it out. So if you run that script without the minus w or the minus s it will just say hello world. If you run it with just the minus s it will say oh you world or if you run it with a minus w without the minus s it will say hello beautiful world or whatever. And you can do both and it will say oh you beautiful world. Probably won't be probably stinky. You probably use minus w stinky or something like oh you stinky world. And if you put in a different minus flag you will get the usage error. Okay. So that is. I think I follow it, yeah. So we are all most done but we've left out one teeny tiny piece. So what about the ordinary arguments? Remember I said this little hand waving thing about we'll just clean up after ourselves. We'll just use this dollar opt ind for the option index. They just clean up. We'll just clean up. How do we just clean up? Well, there is a wonderful command that exists in bash and many other shells called shift. And the shift command takes the first argument and makes it vanish. And it updates dollar zero, one, two, three, four, five, six, sorry, it updates dollar one to nine, dollar star and dollar at as if the first argument had never existed. And then if you shift again another one disappears and dollar one, two, three, et cetera and dollar at and dollar star they all update. So we now know the shift one to the left. The shift one to the left. And if you give shift an argument they will shift that amount to the left. That number, okay. So we will know that one more than we want to get rid of will be contained in the variable named dollar opt ind. So we need to shift. It's always looking to the next one. Because it's always pointing out where it going next. So we need to do the math. Now at the moment based on our knowledge of bash so far we only know how to do mathematics using the BC for basic calculator commands. So for us, we echo dollar opt ind minus one to BC and it will do the math for us. And then we take the result of that and pass it a shift. So for us, it's shift dollar open round you bracket for run this command for me. Echo quoted dollar opt ind minus one pipe BC. In other words, we take the string whatever opt ind is minus one. We shove that into the calculator. We take the result and we give that to shift. Okay. That is because we don't know that there is a bash way of doing math because that's on our agenda for very shortly. So if you prefer to skip ahead and just make a text expander shortcut now you will make that shortcut for shift open quote dollar bracket bracket. Notice dollar bracket bracket we have never seen before opt ind minus one bracket bracket. That will do the math properly. But you don't know why that works because I haven't told you yet but you can make the text expander snippet now and just get into the habit of doing it right. I like the one with the calculator in part. The one with the title makes sense to me. I feel like so much of this is because of the limitations of the number of characters. It's like, well, we're gonna have like 14 roundy brackets. You call them brackets and that never sounds like a parenthesis. I should be saying parenthesis, yeah. But I'm feeling we're gonna have 42 parentheses around something at some point to say because they've only got so much vocabulary. That is true. Now, I'm happy to say there was nothing that I'm not aware of any of that triplicate but there are, yeah, they do duplicate. Like you say, run out of symbols. So we can update our example. You have one final example, PBS149E where instead of saying hello world we're going to say hello to a person. So we expect one argument always which is going to be the name to say hello to. And we are going to use the minus S for snark but instead of a minus W for an adjective to describe the world I'm just gonna say minus A for an adjective to describe the person. So in this case, we're gonna have a minus S as a flag and a minus A as an option, as an optional argument. And we are always going to want the name as a normal plain old argument. So we have a bit of books. I'm not quite caught up on why we need to do this whole getting rid of, getting opt-in set back to nothing but I'm hoping I'm gonna understand this now. Okay, well we'll step through this code and then we will describe at what point in time the code would collapse in a heap if we didn't feed up. And it would collapse in a heap. So very similar B snarky becomes equal to an empty string and this time I've renamed my variable from world adjective to just adjective and I'm defaulting it to brilliant because I think I'd like to be brilliant today. So we're defaulting it to no snark and brilliance. Because there are multiple ways things could go wrong I'm going to save that usage string into a variable called usage instead of copying and pasting it all over the place. So that is the same syntax we've seen before but this time name is a third argument on the back which has no minus flag in front of it and no square brackets. Remember square brackets is how you traditionally symbolize optionality and the name is not optional so it's no square brackets. So we're saying you can give me a minus S you can give me a minus A with a value and you must give me a name. That's what we're saying. Okay. Okay, so we're doing our standard stuff here while get ups and then we pass it the string colon SA colon. So we want a flag S and an optional argument A we then choose the name of where we're gonna store these flags when there are these options when they're found we're calling it opt. Do case dollar opt in S echo enabling snark B snarky equals one echo saving the custom adjective opt arg, adjective becomes equal to opt arg question mark. Sorry, this is insane echo dollar usage exit one. So all the usual stuff. Now imagine we skip the next line that says clean up after ourselves. We now say name becomes equal to dollar one. If they ran the script without the minus S and without the minus W then dollar one is indeed the name. If they ran the script with a minus S dollar one is minus S. If they ran the script with a minus W but no minus S then dollar one is minus W. Sorry, minus A today. So if they use a flag dollar one will be whatever flag they happen to use first. Right, right. That's why we have to clean up after ourselves. Otherwise we can't. How do we get at the name? It could be. So we don't know whether it's gonna be one or two. It could be one or three. Well, no, it could be. So if they passed only a minus S then if they passed nothing it would be at one. If they passed a minus S only it would be at two. If they passed a minus W only because it takes a value it'll be at three. And if they passed the W only. Wait, wait, wait, wait. No, no, no. Sorry, minus A, minus A, minus A. Minus A, apologies. So backing up. If they do nothing it would be dollar one. Yes. The name would be dollar one. If they did a minus S it would be dollar two. If it did minus A it would be dollar three or would it be dollar four? It would be dollar three because you have minus A followed by the adjective. So minus A stinky or whatever. So it'd be four? Name it before. No, no, it would be three. Okay, so minus A stinky only takes up one. No, no, minus A stinky takes up two. But I've already got a minus S there. No, no, okay. I'm saying, no, no. If you only passed at a minus A then it would be at three. If you passed at a minus S and a minus A it would be at four. Okay, good. Okay, that makes sense. So it could be anywhere between one and four. Inclusive. Right, okay. So we do need to clean up because otherwise we can't get our name in a sensible way. So we clean up by doing our shift opt in minus one. So if you just passed me the S then opt in will be two. So we want to throw away just the minus S. So we want to throw away two minus one. If you only passed me the minus A followed by the adjective then opt in would be at three. We want to throw away two. So three minus one is two. Okay. You're seeing how this is working. So that can be my text expander snippet is that shift dollar echo dollar opt in minus one going to the calculator. Okay. Yeah, cause that would just work. It doesn't matter how many they passed that will restore sanity. And then whatever normal arguments that were after the options will now be left as dollar one, two, three, four, et cetera. Okay. And dollar at and dollar star have also been updated. So if we want to take the arguments into an array it's there for us. And then we can just carry on as before we can build up our greeting and we can echo it out. And I have a note to myself saying, well, trying to decide whether or not I tell you that you can cuddle, you can cuddle optional arguments on one condition. They have to be the last thing in the cuddle. So you can have minus SA, but you can't have minus AS. Oh, because the A needs a value as the next argument. So you can't cuddle on the, you can't cuddle on the right of an optional argument, but you can cuddle some flags on its left. So you can say minus SA. Okay. And you know this without knowing it because how many times have you done a get commit minus AM? Follow by a message. So that's minus A flag for commit everything, minus A for all, and the minus AM optional argument for a message. Right, right. So that's minus A minus AM message, but you do minus AM the message. Right, right. So that's you cuddling a flag with an optional argument. I get it. So that is it. Now, can you see why I spent so long today trying to write these notes? Like at the end of the day, the sample code is not complicated. But answering the question, why? Why is it like this, Bart? That not easy. Now I really think you should have tried to work the, what is it at? Wait, what was it? Dollar star and dollar at? Into your last example. No. I'm glad I'm doing video, Bart's head just exploded all over the room. Now I do have an optional challenge for you. Good. So taking our menu, I would like you to add a minus L optional argument for the limit, because that makes a lot more sense than just having it as a bare number stuck on the end as a normal argument. It should be a minus L for limit. I would also like you to add a support a snarky flag. I think you can manage being snarky in your menu. I'm definitely going to do it when the limit command comes up. There was no question I'd already planned that, right? There you go. So that is your challenge. So that will give you an opportunity to play around with a flag and an optional argument. That sounds fun. Well, Bart, we have a new ending. Well, we do. But before that, let's just take a moment and look at the forest. So I am saying to you, I want you to write shell scripts that are completely at home in the terminal. And we are darn close, right? Because we can now do our little flags and they can even be cuddled up together. We're doing really well here. What we're still missing is having our script behave properly inside a pipeline. So piping something to our script and having our script send its output to another command through a pipe. So, bloody, you know, grep something out of their pipe, our script. Our script should be able to accept a barf of information from another command. Like a grep command or whatever, right? So we're not yet ready to play ball inside a chain of pipes. So we need to learn how to do the plumbing. Or rather, we need to learn how to... The terminal will plum in the input, but our script has to actually consume that input. Right, right. You can lead a horse to water. You can give a shell script input, but the shell script's code has to actually consume that input. And so that is where we need to go next so that we can fit into a chain of pipes. So we can do our terminal plumbing properly. And yes, so I would like to remind everyone what we said at the top of the show. There is a community of amazing people. They're hiding over in Allison's Slack. And Allison is very good at running a Slack. So PBS.com, not PBS. Is that anything? Putty.com. Putty.com, forward slash slack. Everything good begins with putty.com. This is how I've learned. So if you go to the Slack, you sign up. There'll be a channel called PenSign or Hash or Rock to Sort PBS. And in there are lots of really cool people talking about all of this stuff. And you can ask your questions and they're all friendly and stuff. And there is no such thing as a silly question. And they will jump over each other to help you, Dern. Yeah, and there's no gate to get into this Slack. You just go there and you get in. And we haven't had anybody misbehave. Nobody, it's just the nicest place. It's very happy and pleasant in there. By the way. Community rocks. This episode proves what Bart always says. He never knows when one's gonna go long and he never knows when it's gonna go short. He said, this could be a short episode. We're at an hour and a half. And only a third of that was because of me being dense. Well, no, I'm sorry. You're doing your job. Asking perfect questions. I was right. Because I think there was a lot of people chatting at their iPods or iPhones or whatever we listen on these days. So anyway, with all of that said between doing your homework and playing in our community, remember folks, there is lots of opportunities where you have lots of happy computing. If you learn as much from Bart each week as I do, I'd like you to go over to let's-talk.ie and press one of the buttons over there to help support him. He does 98% of the work here. I'm just the stooge that listens to him and asks the dumb questions. If you go over to let's-talk.ie you can support him on Patreon. You can donate via PayPal or you can use one of his referral links. I really hope you'll go over and help him out. In the meantime, you can contact me at Podfeed or check out all of the shows we do over there over at podfeed.com. Thanks for listening and stay subscribed.