1
00:00:02,980 --> 00:00:09,800
In this lesson you'll learn how to process command line options using the shell built in getups if you

2
00:00:09,800 --> 00:00:13,310
want your shell scripts to behave like other Linux executables.

3
00:00:13,310 --> 00:00:19,490
You're going to want to allow users to specify options that change the behavior of your scripts.

4
00:00:19,490 --> 00:00:24,980
For example you might want to give the user of both option where the user sees a lot of output from

5
00:00:24,980 --> 00:00:25,750
your script.

6
00:00:25,910 --> 00:00:31,430
Or maybe you want to give them a quiet option where your script does its work silently and then only

7
00:00:31,430 --> 00:00:33,700
reports if it has an error.

8
00:00:33,740 --> 00:00:39,620
Probably one of the first commands you learn how to use on a Linux system was less right after learning

9
00:00:39,620 --> 00:00:47,420
that ls lists files you probably learned about the dash l option which makes LS list files in a long

10
00:00:47,480 --> 00:00:53,870
listing format giving you more information using get ups helps you not only provide such functionality

11
00:00:53,870 --> 00:00:58,770
in your scripts but also helps you to conform to Linux programming conventions.

12
00:00:58,850 --> 00:01:03,560
Knowing what you've learned so far you could use an if statement or a case statement to check for individual

13
00:01:03,560 --> 00:01:06,810
options like Dasch L or dash A.

14
00:01:07,010 --> 00:01:12,550
However if you want to allow the user to combine those short options together so that Dasch L-Space

15
00:01:12,560 --> 00:01:17,850
Dasch a performs exactly like a dash L.A. or dash a.

16
00:01:18,170 --> 00:01:21,290
Doing that with a simple case statement is actually kind of hard.

17
00:01:21,440 --> 00:01:26,160
And get UPS handles this and other little gotchas when working with options.

18
00:01:26,270 --> 00:01:29,660
And that's one of the reasons why we're going to use it here today.

19
00:01:29,990 --> 00:01:31,190
OK let's get to it.

20
00:01:31,190 --> 00:01:37,640
I've got a terminal open on my local machine and I'm going to go into our class folder of shell class

21
00:01:38,000 --> 00:01:43,670
and then we're still working on the local users vagrant project and I'm going to bring up the system

22
00:01:43,670 --> 00:01:52,190
with vigor and up.

23
00:01:52,340 --> 00:01:56,200
Hey let's move into our shared folder of forward slash vagrant.

24
00:01:56,430 --> 00:02:01,880
Now first off getups is a shell built in and we can tell this by running the type command against it

25
00:02:01,880 --> 00:02:06,080
will do type Desch a g e t o p t s.

26
00:02:06,090 --> 00:02:09,060
And sure enough it is a shell built in.

27
00:02:09,270 --> 00:02:14,520
As you already know I recommend using shell built ins whenever possible because it makes your script

28
00:02:14,580 --> 00:02:15,800
more portable.

29
00:02:15,810 --> 00:02:19,040
That's one of the reasons why we're going to be using get ops.

30
00:02:19,050 --> 00:02:25,890
There is a very similar command called Get Opt. that singular that you might see in some older scripts.

31
00:02:25,890 --> 00:02:31,440
Get up is an executable on the file system so it will do type Desch a get up and sure enough that is

32
00:02:31,440 --> 00:02:33,810
located on this particular system in user bin.

33
00:02:33,810 --> 00:02:35,790
Get up Get up.

34
00:02:35,820 --> 00:02:42,030
Is very similar to get ups but it has its limitations in its own set of unique quirks.

35
00:02:42,030 --> 00:02:47,010
If you're interested in learning more about it or you end up having to dive into the details of it at

36
00:02:47,010 --> 00:02:53,340
some point because you run across a script that has to get up in it then just read the man page on get

37
00:02:53,340 --> 00:02:55,560
up and you'll be well on your way.

38
00:02:55,560 --> 00:02:59,560
Now let's get some help on the get UPS built in function here.

39
00:02:59,610 --> 00:03:02,290
So do help get ops.

40
00:03:02,340 --> 00:03:07,950
Actually let me pipe that to less so we can actually read what it says here on the screen and its usage

41
00:03:07,950 --> 00:03:08,250
is.

42
00:03:08,250 --> 00:03:11,010
Get ups Opt. string name.

43
00:03:11,100 --> 00:03:16,700
And as we know anything in brackets is optional so you have an optional argument there on the end.

44
00:03:17,460 --> 00:03:22,590
Now instead of me reading this entire Help section to you just let me quickly summarize it and we'll

45
00:03:22,590 --> 00:03:24,420
start using it right away.

46
00:03:24,540 --> 00:03:29,070
So the Opt. string is something that you are going to provide.

47
00:03:29,070 --> 00:03:33,420
These are the options that your script is going to recognize and accept.

48
00:03:33,420 --> 00:03:36,640
It's just a series of letters that are going to be your options.

49
00:03:36,810 --> 00:03:41,630
If you want to make an option mandatory then follow that letter option with a colon.

50
00:03:41,670 --> 00:03:44,010
Next you're going to provide a name.

51
00:03:44,040 --> 00:03:48,220
It's a variable that's going to get populated with an option.

52
00:03:48,240 --> 00:03:53,430
That way you can do something based on that option because you have no idea what a user is going to

53
00:03:53,430 --> 00:03:56,750
do and how many options they may try to supply.

54
00:03:56,970 --> 00:04:04,700
You'll need to use get ups in a while loop get ops returns 0 as long as it finds an option to process.

55
00:04:04,830 --> 00:04:09,630
Otherwise it returns one which will cause the while loop to exit.

56
00:04:09,630 --> 00:04:14,350
Finally get ups parses positional parameters by default but you can make it parse.

57
00:04:14,360 --> 00:04:18,950
Something else entirely by providing it with an argument at the end.

58
00:04:19,170 --> 00:04:26,010
All right so let's write a script that uses get ups.

59
00:04:26,130 --> 00:04:39,410
Let's make this script generate a password.

60
00:04:39,410 --> 00:04:42,930
Let's also give the users some control over what happens here with a script.

61
00:04:42,950 --> 00:04:50,060
We'll let them specify a password length with a dash l option and whether or not to use a special character

62
00:04:50,330 --> 00:04:52,120
with the dash s option

63
00:05:06,850 --> 00:05:12,730
and let's let them control the verbosity or level of output that is going to be displayed to the screen.

64
00:05:18,950 --> 00:05:22,540
Because a user can optionally specify a password length.

65
00:05:22,550 --> 00:05:25,270
Let's go ahead and set a default value for that

66
00:05:30,790 --> 00:05:39,640
will use the variable length and we'll send it to 48 characters long this default value will be overridden

67
00:05:39,640 --> 00:05:41,500
with whatever the user provides.

68
00:05:41,530 --> 00:05:47,800
If they decide to specify a password length with the dash l option which we're going to account for

69
00:05:47,800 --> 00:05:48,950
in just a second.

70
00:05:49,340 --> 00:05:55,600
Now what we're going to do is use a while loop in conjunction with the get ups command in the while

71
00:05:55,600 --> 00:06:00,180
loop we're going to use a case statement to do something based on the option provided.

72
00:06:00,220 --> 00:06:06,420
This is the structure you're going to see and use when processing command line options.

73
00:06:06,470 --> 00:06:09,630
All right I'll just start the while command here will do while yet.

74
00:06:09,640 --> 00:06:12,010
Ops This is our OP string.

75
00:06:14,140 --> 00:06:17,500
And this is our variable name.

76
00:06:17,530 --> 00:06:18,960
Now remember we have to tell.

77
00:06:18,960 --> 00:06:22,000
Get ups what options are valid here.

78
00:06:22,000 --> 00:06:27,970
We're going to allow the dash via option the dash l option and the dash s option.

79
00:06:27,970 --> 00:06:33,190
That's why we have the characters Violette's and the OP string if you want to make an option have a

80
00:06:33,190 --> 00:06:41,950
mandatory value although that option with a colon by using the L colon as we are saying that the dash

81
00:06:41,980 --> 00:06:46,460
l option must be followed with an argument of its own for this script.

82
00:06:46,480 --> 00:06:50,380
We want the user to supply a link to the dash l option.

83
00:06:56,650 --> 00:07:00,120
Now we're going to use a case statement to process our options.

84
00:07:26,020 --> 00:07:33,490
When an option requires an argument getups places that argument into the shell variable opt ARG here

85
00:07:33,490 --> 00:07:37,430
were signing that arguments value to the link variable.

86
00:07:37,600 --> 00:07:44,490
If the user were to execute our script with Dash L4 then four will be assigned to opt Argin here.

87
00:07:44,500 --> 00:07:50,100
We're assigning that value of 4 into the length the variable that we'll be using later on in the script.

88
00:08:20,950 --> 00:08:26,000
By the way you could have used an asterisk as the catchall pattern in the case statement but get obs

89
00:08:26,030 --> 00:08:29,610
is giving us a single character option at a time.

90
00:08:29,630 --> 00:08:34,280
So I decided to use the pattern for a single character which is the question mark.

91
00:08:34,460 --> 00:08:36,270
We'll come back to this section in the second.

92
00:08:36,290 --> 00:08:39,760
But first let's see what we have so far.

93
00:08:47,680 --> 00:08:51,370
OK that's dash V for the verbose option and that seems to work.

94
00:08:51,700 --> 00:08:55,500
That just doesn't display any output because we didn't tell it to.

95
00:08:55,570 --> 00:09:00,120
Let's see what happens when we run it with Dash L we get an error.

96
00:09:00,130 --> 00:09:06,460
So get ups is taking care of this situation for us it's saying hey this option requires an argument.

97
00:09:06,610 --> 00:09:10,370
So we'll go ahead and give it an argument and that looks good.

98
00:09:10,370 --> 00:09:13,060
Again we didn't print anything or do anything in that case statement.

99
00:09:13,060 --> 00:09:15,630
So this is expected behavior at this point.

100
00:09:15,670 --> 00:09:18,600
So let's do this given an option that is invalid.

101
00:09:18,610 --> 00:09:22,870
So we'll get that here and it says illegal option X..

102
00:09:23,080 --> 00:09:25,000
OK so this is a good basis for our scrip.

103
00:09:25,000 --> 00:09:27,530
Now let's jump back in and continue building this out.

104
00:09:28,600 --> 00:09:34,870
Instead of echoing in valid option to the screen and exit teaching I want to teach the user how to use

105
00:09:34,870 --> 00:09:35,950
this script.

106
00:09:35,950 --> 00:09:39,270
In theory I could place that code right in the case statement.

107
00:09:39,280 --> 00:09:44,030
However I think it's going to be several lines long so I'm going to put it into a function.

108
00:09:44,050 --> 00:09:46,830
This makes the case statement easier to read.

109
00:09:46,870 --> 00:09:51,930
Again this is a pure judgment call you can do this without a function if you want to.

110
00:09:51,940 --> 00:09:54,310
So here I'm going to do this.

111
00:09:54,310 --> 00:10:00,800
I'm going to get rid of this and instead I'm going to say usage.

112
00:10:00,860 --> 00:10:05,080
Now we have to go back to the top of our script and define this usage function.

113
00:10:05,120 --> 00:10:09,610
Again it's a best practice to place all your functions at the very top of your script.

114
00:10:09,710 --> 00:10:18,720
So I go up here and I will say usage will do this here.

115
00:11:22,690 --> 00:11:29,140
So here we have a function that displays the usage we're modeling our usage here after man pages and

116
00:11:29,140 --> 00:11:30,830
the help built in command.

117
00:11:30,940 --> 00:11:34,870
We're putting optional options within brackets and so on and so forth.

118
00:11:34,870 --> 00:11:39,590
We're giving some information about what those options are and then we're going to exit the script with

119
00:11:39,590 --> 00:11:44,680
the next status of one because if they've ended up here that means they've used an invalid option or

120
00:11:44,680 --> 00:11:45,920
something like that.

121
00:11:45,940 --> 00:11:49,210
So we're going to exit with a non zero exit status.

122
00:11:49,240 --> 00:11:50,920
So let's try this out.

123
00:11:53,880 --> 00:12:02,040
Our user demo 11 dash X and it says a legal option X that's coming from get ups and then what has happened

124
00:12:02,040 --> 00:12:08,640
is our catchall of the question mark in our case statement has been executed or that has been matched

125
00:12:08,910 --> 00:12:14,700
and the code underneath it which is usage causes us to execute the code in the usage function that we

126
00:12:14,700 --> 00:12:17,690
declared and then we get this information to our screen.

127
00:12:17,730 --> 00:12:22,680
Now our exit status should be one because that is what's going on in that function.

128
00:12:22,680 --> 00:12:30,660
So let's just check it real quick and sure enough the exit status is one.

129
00:12:30,840 --> 00:12:35,810
If we're in verbose mode we want to tell the user everything that is happening in the script.

130
00:12:36,030 --> 00:12:37,610
So let's do a little check.

131
00:12:37,620 --> 00:12:45,850
Let's go down here after the case statement and the while loop and we'll do this

132
00:13:03,670 --> 00:13:05,350
so this is the type of check we need.

133
00:13:05,350 --> 00:13:10,810
But if we need to check the verbose variable every time we want to display something to the screen that

134
00:13:10,810 --> 00:13:14,740
is going to be a lot of duplicated code and repeated work.

135
00:13:14,950 --> 00:13:18,190
So in the spirit of keeping things dry don't repeat yourself.

136
00:13:18,340 --> 00:13:24,760
We're going to move this check into a function so I'll just actually delete this and move it back up

137
00:13:24,760 --> 00:13:25,840
to the top here.

138
00:13:31,020 --> 00:13:34,570
So what we'll do is call log.

139
00:13:34,620 --> 00:13:39,000
Now I'm not the biggest fan of that name because we're not actually going to write anything to a log

140
00:13:39,000 --> 00:13:44,820
file and this particular script but it works for demonstration purposes here gives you an idea of what

141
00:13:44,820 --> 00:13:47,270
is happening or what this function does.

142
00:13:47,280 --> 00:13:54,990
Now perhaps we could have named this function something like local echo or display or say or probably

143
00:13:54,990 --> 00:14:00,690
something that I like better or something more verbose like send to standard out or something else that

144
00:14:00,690 --> 00:14:01,400
you dream up.

145
00:14:01,410 --> 00:14:03,860
Anyway I'm going to go with log here for now.

146
00:14:03,860 --> 00:14:05,730
It's going to work for our purposes.

147
00:14:05,760 --> 00:14:12,880
So what are we going to do is have a local variable called message and we're going to assign that any

148
00:14:12,880 --> 00:14:16,090
anything that has been passed into this function.

149
00:14:17,650 --> 00:14:19,560
Now we'll just do our check here.

150
00:14:20,380 --> 00:14:24,860
If verbose is true then we'll echo whatever that message is to the screen.

151
00:14:33,660 --> 00:14:33,910
OK.

152
00:14:33,920 --> 00:14:35,850
And that wraps up our little function.

153
00:14:36,050 --> 00:14:38,950
So now that we have a function we need to call it instead.

154
00:14:38,990 --> 00:14:42,300
So we'll go down to the bottom of our script here.

155
00:14:43,230 --> 00:14:50,510
And instead of doing an echo we'll do log generating a password.

156
00:14:50,580 --> 00:14:56,190
Also we can replace the echo command with the log function for the initial verbose message above.

157
00:14:56,190 --> 00:14:57,900
So we have echo here.

158
00:14:58,020 --> 00:15:02,680
So all we can do the same thing or just log here to be consistent.

159
00:15:02,740 --> 00:15:08,480
Kate let's see if this works so we'll do our script name here and we'll do a dash of the option.

160
00:15:08,780 --> 00:15:14,110
Hey sure enough verbose mode gets printed to the screen generating a password also gets displayed to

161
00:15:14,110 --> 00:15:14,890
the screen.

162
00:15:14,890 --> 00:15:18,070
Well let's see what happens if we don't use for bus mode.

163
00:15:18,490 --> 00:15:18,780
OK.

164
00:15:18,790 --> 00:15:24,580
Nothing gets echoed to the screen even though we had that log that says generating a password.

165
00:15:24,700 --> 00:15:27,760
Well that log function checked a verbose mode was set and it wasn't.

166
00:15:27,760 --> 00:15:32,600
So it did not display it to the screen so this is doing exactly what we wanted to do.

167
00:15:35,730 --> 00:15:37,860
So now it's actually generate a password.

168
00:16:03,080 --> 00:16:06,860
I just stole that little line of code from one of our earlier lessons.

169
00:16:06,890 --> 00:16:11,900
The main thing to point out here is that we're using the variable length we set the default value to

170
00:16:11,900 --> 00:16:17,070
be 48 but a user can change that with a dash l option.

171
00:16:17,070 --> 00:16:22,500
Now let's see if we need to append a special character to the password or not and we can do a simple

172
00:16:22,500 --> 00:16:24,240
check with an if statement.

173
00:17:32,360 --> 00:17:38,800
Again the couple of lines of code here that do the actual work were covered in an earlier lesson.

174
00:17:39,200 --> 00:17:41,930
Let's tell the user that we're done and then just give them the password

175
00:18:05,520 --> 00:18:10,840
and wanted to point out that the reason I'm using the echo statement directly to display the password

176
00:18:10,840 --> 00:18:16,600
is that I want to display that password no matter if the verbose mode is on or not.

177
00:18:16,840 --> 00:18:19,620
So let's check our work at the command line here.

178
00:18:22,120 --> 00:18:27,540
OK we get a random password that's 48 characters in length by default so that looks good.

179
00:18:27,540 --> 00:18:34,560
Let's append the dash s and sure enough you can see that a special character is appended to the end.

180
00:18:34,560 --> 00:18:39,320
Let's do this with verbose mode.

181
00:18:39,460 --> 00:18:44,720
Sure enough now it says verbose mode is on regenerating a password we're selecting a random character.

182
00:18:44,830 --> 00:18:51,130
We're all done and here's your password so that's very very wordy or very verbose so obviously the verbose

183
00:18:51,190 --> 00:18:52,640
mode is doing its job.

184
00:18:52,960 --> 00:18:58,830
Now by the way something that get ups handles for us here is a convention where you can not only do

185
00:18:58,830 --> 00:19:07,630
s v but you can do Dasch the S which is the same as dash of the dash s or dash dash V.

186
00:19:07,960 --> 00:19:15,760
OK now let's try specifying a length so we'll do dash l dash 8 and sure enough we get a password that

187
00:19:15,760 --> 00:19:22,840
has eight characters in it and lets also combine this with a dash s option to append a special character.

188
00:19:22,870 --> 00:19:27,400
All right so we have a password that's 8 in length plus one plus a special character.

189
00:19:27,400 --> 00:19:32,200
Again we could go back and really revise the script and get specific and really make sure that if we're

190
00:19:32,200 --> 00:19:38,230
adding a special character that we chop off a character from the password before it is actually truly

191
00:19:38,230 --> 00:19:39,410
eight characters.

192
00:19:39,430 --> 00:19:44,590
Again I'm of the mind that this probably is close enough this gets us like 90 percent of the way there

193
00:19:44,860 --> 00:19:50,430
without going in and doing some even more complex work that in the end probably truly doesn't matter.

194
00:19:50,500 --> 00:19:52,900
For our practical use case here.

195
00:19:53,300 --> 00:19:59,500
OK so at this point we could really stop here because our script does exactly what we want it to do.

196
00:19:59,530 --> 00:20:04,990
However I want to show you how to handle additional command line arguments beyond the options that you

197
00:20:04,990 --> 00:20:12,010
are taking care of with get ops in order to do that we need to talk about arithmetic expansion and arithmetic

198
00:20:12,010 --> 00:20:12,990
evaluation.
