YouTube2Text

Become a bash scripting pro - full course — Transcript

by Terminal Velocity · 7,336 words · 987 segments · language en · Watch on YouTube

Full transcript

  1. 0:00hey folks so in this video I want to
  2. 0:02teach you the superpower that is Bash
  3. 0:05scripting and a superpower it is it's
  4. 0:08one of those things that you can pick up
  5. 0:10really quickly as you'll see here I'm
  6. 0:12going to teach you virtually everything
  7. 0:14that you'll need to know to write any
  8. 0:16script that you'll ever write and once
  9. 0:17you get in the habit of writing bash
  10. 0:19scripts it's one of those things that is
  11. 0:21a real Force multiplier things that you
  12. 0:23would do manually often and you just
  13. 0:25deal with are things that you can
  14. 0:27automate very easily in a matter of
  15. 0:29minutes and you'll never have to do
  16. 0:31manually again so let's walk through it
  17. 0:34so I've written a lot of bash scripts
  18. 0:35over the years I've tried to gather all
  19. 0:38of the knowledge that I've gained and
  20. 0:40extract essentially everything that I
  21. 0:43know that you need to know to write
  22. 0:45virtually every script that I've written
  23. 0:47and none of the weird things that you're
  24. 0:48not going to need to know because there
  25. 0:50are weirdnesses in the language but you
  26. 0:53really don't need to deal with them the
  27. 0:55majority of the time so let's get right
  28. 0:57into it it does build on a knowledge of
  29. 0:59the shell and how to actually use bash
  30. 1:02so if you're not familiar with the
  31. 1:03command line and all that I did put out
  32. 1:04a video a couple weeks ago that you can
  33. 1:06check out to refresh your knowledge or
  34. 1:08or learn for the first time otherwise
  35. 1:11let's check it out so to create a bash
  36. 1:14script it's just a file like anything
  37. 1:16else typically it'll have the sh
  38. 1:18extension so got this hello.sh here so
  39. 1:22the first line should always be the
  40. 1:23shebang it's a fun word but what it is
  41. 1:27is a way for you to tell your shell what
  42. 1:30interpreter to use for this script so
  43. 1:32here we've got and this is a comment so
  44. 1:34it starts with a hash and you do an
  45. 1:37exclamation point or a bang and then you
  46. 1:39give it the path to your interpreter in
  47. 1:42this case we're using bash a good
  48. 1:43practice is to use this user bin EnV and
  49. 1:46then passing the argument of The
  50. 1:48Interpreter so in this case bash and
  51. 1:50what this EnV tool does is it'll check
  52. 1:53in your system where the correct
  53. 1:54location of bash is and we'll talk about
  54. 1:57how the path Works in a bit but suffice
  55. 1:59to say this will make sure that it's
  56. 2:01running the correct instance of bash for
  57. 2:04your system a common problem that you'll
  58. 2:06see is people do something like this
  59. 2:07where it's hardcoded the path of Bin
  60. 2:10bash but that's not portable some
  61. 2:12systems like mine for instance like I
  62. 2:14don't have bash in that path and so if I
  63. 2:17try to run a script that has been bash
  64. 2:20declared it's going to fail out
  65. 2:21instantly so that's no good so bash you
  66. 2:24know being a shell language is very
  67. 2:26command focused and this is what makes
  68. 2:29it so easy to work with anything that
  69. 2:31you've run on your command line you can
  70. 2:34run directly the same exact way inside
  71. 2:36of the script so Echo hello YouTube you
  72. 2:39could do that in your command line you
  73. 2:41can do that exactly the same here you
  74. 2:43got your command space and your argument
  75. 2:46it has access to all of the same things
  76. 2:48that you have in your system so I can
  77. 2:50run G settings which is a gome utility
  78. 2:52for setting things in the desktop
  79. 2:55manager so you can set the color scheme
  80. 2:57for instance again you can also do
  81. 2:59things like
  82. 3:00pipelines so we can do this Cube control
  83. 3:02command which passes into the fuzzy
  84. 3:04finder ax some stuff and eventually runs
  85. 3:07through and does a cube control describe
  86. 3:09against the pod that's a long command
  87. 3:12and that's something that now by virtue
  88. 3:14of having an A bash script you don't
  89. 3:16ever need to remember how to write it
  90. 3:18out manually you can just refer to the
  91. 3:20script that's the real power of this you
  92. 3:22know we've learned one feature which is
  93. 3:24calling commands and even with just that
  94. 3:27even if there's nothing else you can
  95. 3:28still get gr value out of using this
  96. 3:31because you can take any series of
  97. 3:33commands that you'd run and now self
  98. 3:35enclose them into a single script but
  99. 3:38there's a lot more to the language so
  100. 3:40let's check it out but first if we go
  101. 3:42back to our simple example of just an
  102. 3:44echo statement if we try to run the
  103. 3:46script we're going to run into some
  104. 3:47problems that's where we need to learn a
  105. 3:49little bit about permissions on unic
  106. 3:51systems so if you run this hello.sh
  107. 3:54script and to run it you give it the
  108. 3:55file path we're doing slash because it's
  109. 3:57in the current directory you're going to
  110. 4:00see this error which says permission
  111. 4:02denied if we run LSL we can see the
  112. 4:05permissions on this file and this is
  113. 4:07going to be true for any type of Unix
  114. 4:09system so if it's Linux or Mac you're
  115. 4:11going to see this where we have these
  116. 4:12file permissions set for the user for
  117. 4:15the group and for everyone else in this
  118. 4:17case we've got read and write
  119. 4:19permissions for the user and we just
  120. 4:21have read permissions for the group and
  121. 4:23for everyone else and that's why we have
  122. 4:26this error because we don't have execute
  123. 4:28permissions so to remedy this situation
  124. 4:30we can run chod which is a command line
  125. 4:33utility that allows you to change the
  126. 4:35file permissions on a file so here we
  127. 4:38have + x which is saying for the user
  128. 4:41add the execute permissions for this
  129. 4:43given file then if we run ls- L again
  130. 4:46you can see now for the user they do
  131. 4:49have read write and execute but the
  132. 4:51group and the others still don't if you
  133. 4:53did want execute permissions for
  134. 4:55everyone you could do just chod plus X
  135. 4:58but just calling the principle of least
  136. 5:00privilege it's always best to default to
  137. 5:03just doing the user and opening it up
  138. 5:05beyond that if needed but with that in
  139. 5:08place now we can run the script and
  140. 5:10it'll run as we'd expect but everything
  141. 5:12so far has been static one of the powers
  142. 5:14of actually using a language is you can
  143. 5:17parameterize things so let's pull out
  144. 5:19the name YouTube into a variable so a
  145. 5:22variable in bash isn't going to be
  146. 5:24defined with let or const or VAR
  147. 5:27anything like that it's just the name of
  148. 5:29the variable in this case name and then
  149. 5:31equals and this is important you can't
  150. 5:34have spaces around the equal sign here
  151. 5:36so it's has to be name equals YouTube if
  152. 5:39you did try to do something like this
  153. 5:41where you have spaces around the equal
  154. 5:42sign because bash being a command first
  155. 5:45language it's going to see this and
  156. 5:47think another is a command and you're
  157. 5:49passing an equal sign and universe as
  158. 5:52arguments but of course another isn't a
  159. 5:54command and that wasn't what we intended
  160. 5:56so that's an error to actually reference
  161. 5:59the variable you just do dollar sign and
  162. 6:01then variable name and that'll be able
  163. 6:04to print out just the same as we had
  164. 6:05before if you do single quotes instead
  165. 6:08of double quotes that doesn't do the
  166. 6:10variable expansion and so that'll print
  167. 6:12out the literal characters you dollar
  168. 6:15sign name instead of expanding to the
  169. 6:17value of the variable so watch out for
  170. 6:19that there's also this format with the
  171. 6:22curly braces so dollar sign curly braces
  172. 6:25variable and we'll see that this has
  173. 6:27some nice properties so you can add
  174. 6:30additional operations against it like if
  175. 6:32you put a hash in front of the variable
  176. 6:34name instead of printing out the value
  177. 6:37of the variable it's going to give you
  178. 6:38the length of the value in this case U2
  179. 6:41being seven characters it prints out
  180. 6:44seven in the place of the variable a
  181. 6:46common situation you'll have is you'll
  182. 6:48have a variable that is undefined and
  183. 6:50you're trying to reference it but if it
  184. 6:53doesn't exist well you're going to get a
  185. 6:54blank slot so instead you can set this
  186. 6:57default value and the syntax looks like
  187. 6:59this where it's within the curly braces
  188. 7:02and you do variable Name colon dash and
  189. 7:06then the value in this case we have
  190. 7:08Anonymous so with name being equal to
  191. 7:11nothing when it gets to this spot it's
  192. 7:12going to see okay name is not said so we
  193. 7:15use the default value though it's
  194. 7:17important to know with this particular
  195. 7:18version if we do Echo name after that
  196. 7:21it's going to be blank again because
  197. 7:23name is still empty we just used the
  198. 7:25default value in that slot however if
  199. 7:28you want to also set the value to the
  200. 7:30default you can use an equal sign
  201. 7:31instead so now it'll print out Anonymous
  202. 7:34as the name on line five there next up
  203. 7:37let's take a look at the subshell the
  204. 7:40subshell is something that you'll end up
  205. 7:41using a lot so the way it works is like
  206. 7:44this you've got a set of parentheses and
  207. 7:47within the parentheses you'll have some
  208. 7:50operation let's take a look at an
  209. 7:52example so if I was to run PWD to get my
  210. 7:55current directory it'll print out that
  211. 7:57I'm in The Bash directory but then if I
  212. 8:00run a command in the subshell where I
  213. 8:03first CD to The Parent Directory and
  214. 8:05then run PWD you can see I'm in the
  215. 8:07videos directory but if I then run PWD
  216. 8:10again from the original shell we're
  217. 8:12going to see we're still in the bash
  218. 8:14directory that's because the CD and any
  219. 8:16operation within that subshell was just
  220. 8:18in the context of that subshell it
  221. 8:20didn't impact what's actually going on
  222. 8:22in my current shell that becomes very
  223. 8:25handy in many use cases but most
  224. 8:28commonly you're going to use it for
  225. 8:29command substitution which looks like
  226. 8:31this where you have a dollar sign and
  227. 8:33then parentheses so you can run your
  228. 8:35command from within the subshell and
  229. 8:37then you can use that anywhere that
  230. 8:38you'd use a value here we're using it in
  231. 8:40a variable assignment and we can then
  232. 8:43use that value anywhere that we want
  233. 8:45here's a more interesting example where
  234. 8:47we're first fetching from an API a Json
  235. 8:50response and then we're using JQ to
  236. 8:53extract a value from that and the way
  237. 8:55that these subshells work with this
  238. 8:56command substitution is it takes the
  239. 8:58final out outp put so image URL will
  240. 9:01just be the literal URL that we get from
  241. 9:04this JQ command and then we can use that
  242. 9:06in the next step to curl from that URL
  243. 9:09there's also this thing called process
  244. 9:11substitution where you're able to treat
  245. 9:13the output of a command like a file so
  246. 9:15in this case we're using the diff tool
  247. 9:17which is expecting two different files
  248. 9:19to be passed in and using the less than
  249. 9:22and then parentheses syntax you just run
  250. 9:24a command and the output of that is
  251. 9:26going to be treated as a file so we're
  252. 9:28going to be comparing the difference
  253. 9:30between these two Ls outputs as if they
  254. 9:32were files there's also the arithmetic
  255. 9:35expansion so got this dollar sign and
  256. 9:37then double parenthesis that's where you
  257. 9:39can actually run any mathematical
  258. 9:41operations and it might be surprising to
  259. 9:43you if you've never tried but if you run
  260. 9:453 + 4 within the shell it's going to say
  261. 9:48something like in this case three is not
  262. 9:50a command and so it has to be within
  263. 9:52this block in most bash scripts you
  264. 9:54write you're going to need some form of
  265. 9:55user input and that often comes in the
  266. 9:57format of command command line arguments
  267. 10:00so for instance in the script that I
  268. 10:02have here where I'm merging a video file
  269. 10:04in an audio file into a single output
  270. 10:07I'm calling the merge AV command that's
  271. 10:09going to be assigned to the zero
  272. 10:11variable the first command line argument
  273. 10:13is going to be the variable one second
  274. 10:15one to two and so on so then from within
  275. 10:17the script what I like to do and I think
  276. 10:19this is a very good practice is to
  277. 10:21create these intermediary variables so
  278. 10:23I've got video input is equal to the
  279. 10:25variable one audio input to two and so
  280. 10:28on and then you just use those
  281. 10:29throughout your script you could if you
  282. 10:31wanted to just directly use 1 two and
  283. 10:33three but if you compare the clarity of
  284. 10:36the top and the bottom here I think it's
  285. 10:38much clearer what those variables
  286. 10:40actually refer to in the top another big
  287. 10:43part of men script is going to be
  288. 10:44conditional logic and that's where if
  289. 10:46statements come in so if statements the
  290. 10:48actual structure is pretty simple so
  291. 10:51it's if some condition is true then do
  292. 10:54this top block L if so if some other
  293. 10:57condition is true but not the the first
  294. 10:59one then this will be performed
  295. 11:01otherwise we'll do this final one in the
  296. 11:03else and we close it out with an fi
  297. 11:05which is just reversed if so all fairly
  298. 11:09conventional if you're wondering why
  299. 11:11there's like a semicolon and then then
  300. 11:12on the same line you could do it on
  301. 11:14separate lines if you wanted to you
  302. 11:15could do if then like this personally I
  303. 11:17think the second form here is kind of
  304. 11:19ugly there is one element of Bash that's
  305. 11:21a little bit strange again being a shell
  306. 11:24first language this is probably why this
  307. 11:26is the way that it is but in other
  308. 11:28languages like if you look at python or
  309. 11:29JavaScript there's a concept of
  310. 11:32truthiness where if you compare 1 is
  311. 11:34equal to one the result is going to be
  312. 11:36true if you compare 1 to two it's going
  313. 11:38to be false well that's not the way that
  314. 11:40it works in bash it uses exit codes
  315. 11:42where the exit code of zero is a success
  316. 11:45an exit code of literally anything else
  317. 11:48whether it be 1 10 200 it doesn't matter
  318. 11:51that's going to be a failure the
  319. 11:52specific number that an exit code has
  320. 11:55Beyond just meaning that it's a failure
  321. 11:56doesn't generally mean anything now a
  322. 11:59specific command or a specific script
  323. 12:01can choose specific numbers and then you
  324. 12:03can do specific error handling based on
  325. 12:06that number but most of the time you'll
  326. 12:08just do something like this where you've
  327. 12:09got an if block you know so if some
  328. 12:12condition if something failed then Echo
  329. 12:14you know do your logging but then exit
  330. 12:16one and that's going to say all right
  331. 12:18stop the program here but we're
  332. 12:20returning to whoever kicked this off
  333. 12:21that this was in fact a failure so what
  334. 12:24this means with this exit code approach
  335. 12:26is that you can run commands as
  336. 12:29conditionals so here we've got an
  337. 12:30example with grep where we're searching
  338. 12:33a logs. text file for any occurrence of
  339. 12:35error and if there's a match that's
  340. 12:37going to be a success that'll return
  341. 12:39exit Code Zero and then we're going to
  342. 12:41do what's in the first block here
  343. 12:42otherwise if there are no matches it's
  344. 12:45going to return the else block all is
  345. 12:48fine in the world now it probably feels
  346. 12:50a little bit weird in this example
  347. 12:51because you'd think that well we have
  348. 12:53errors in our logs. text surely that's
  349. 12:55not a good thing but you got to remember
  350. 12:57it's in the context of GP trying to
  351. 13:00search for a match the match itself is
  352. 13:02the success state so that's why that is
  353. 13:04how it is but most of the time you don't
  354. 13:06need to worry about that most of the
  355. 13:08time you'll be doing conditionals and
  356. 13:10Bash has a lot of conditionals so the
  357. 13:12built-in conditionals use this testing
  358. 13:15syntax which has this double square
  359. 13:16brackets and it kind of uses a
  360. 13:19command-like syntax where you need to
  361. 13:20have spaces around everything if you
  362. 13:22have everything squished up it's going
  363. 13:24to be a syntax error so make sure there
  364. 13:26are spaces again your editor should warn
  365. 13:28you about that but we can see we have
  366. 13:30things like string comparisons you're
  367. 13:32used to like the double equals or not
  368. 13:34equals but for numerical comparisons you
  369. 13:37have to use these short codes of- EQ or-
  370. 13:41NE and so on you also have ones like
  371. 13:43this for variable existence so you can
  372. 13:45do- Z to see if something is empty or
  373. 13:48dasn to see if it's not you can do file
  374. 13:50checks to see if things exist you can
  375. 13:51check what the permissions are and you
  376. 13:53can also combine them so you can do d a
  377. 13:56or- o for logical and or or or can also
  378. 14:00do it externally with the double Amper
  379. 14:02sand or the double pipe for the and or
  380. 14:05the or my preference is to use the
  381. 14:07external because it makes more clarity
  382. 14:09in my mind as to where the separations
  383. 14:11are you can do internal if you like as
  384. 14:13well okay we've been talking language
  385. 14:16specifics for a little bit I just want
  386. 14:17to show off a couple useful commands
  387. 14:19that you're going to want in a lot of
  388. 14:21scripts that you write so first is sleep
  389. 14:24probably familiar with this you can just
  390. 14:26say how many seconds you want to sleep
  391. 14:27for and it's as simple as that we'll see
  392. 14:29an example of this later on there's also
  393. 14:31the read command for getting user input
  394. 14:34throughout your script so you can do
  395. 14:35something simple like this where we're
  396. 14:37asking for the user's name and the
  397. 14:40command is just read and you can pass in
  398. 14:42the variable that you want to assign the
  399. 14:44output to so if I run the script what is
  400. 14:47your name give it my name and then it'll
  401. 14:49use that as the variable that it's
  402. 14:51printing out more often than not the way
  403. 14:54that I use this is for approvals or
  404. 14:56input steps where something is happened
  405. 14:59and you want to make sure that the user
  406. 15:00wants to proceed from this point and so
  407. 15:02you can do something like this where you
  408. 15:04say do you want to continue if they
  409. 15:05don't say yes you can exit out probably
  410. 15:07want to have a little bit more Nuance to
  411. 15:10it than this simple example but this
  412. 15:12kind of idea is very common back to bash
  413. 15:15specifics as I've mentioned before bash
  414. 15:17is a strange language and I want to talk
  415. 15:20a bit about the behavior and how we can
  416. 15:22make it a little bit more pleasant to
  417. 15:24work with so if you're familiar with
  418. 15:26JavaScript or Pearl you might be aware
  419. 15:28that there's a strict mode with those
  420. 15:30languages but the idea is you can make
  421. 15:32things a bit more strict so you're more
  422. 15:34likely to encounter errors to make your
  423. 15:37code better there's this command that is
  424. 15:39often called the strict mode of bash
  425. 15:42which is this set- euo pipe fail which
  426. 15:46is a combination of these three commands
  427. 15:48that set some different behaviors so
  428. 15:50let's walk through this just so we can
  429. 15:51understand what's going on so if you
  430. 15:53don't have set- e what happens is a very
  431. 15:56weird Behavior so the false command here
  432. 15:59is just going to be a failure it should
  433. 16:01exit the program or that's what you'd
  434. 16:03expect but with bash when something
  435. 16:06fails the script just keeps on going
  436. 16:08which is not good behavior so that's
  437. 16:11what set- e resolves if we run false
  438. 16:14again the program will just exit
  439. 16:16immediately it's not going to continue
  440. 16:17on to the next step that's good because
  441. 16:19typically in an imperative language
  442. 16:22you're going to expect that everything
  443. 16:23is going to be building on top of each
  444. 16:25other so if one thing is failed you
  445. 16:26really don't want the next step to
  446. 16:28proceed because you're at that point
  447. 16:30expecting that the previous things have
  448. 16:31succeeded so I would always use this
  449. 16:35though as an aside there is this thing
  450. 16:37called conditional execution where you
  451. 16:39can say command one and then double
  452. 16:41Amper sand command two where it'll say
  453. 16:44if command one succeeds then run command
  454. 16:48two or you can opt for if command one
  455. 16:51fails then run command two but if
  456. 16:53command one succeeds then just skip
  457. 16:55command two Al together these can to be
  458. 16:57very handy in the these situations where
  459. 16:59we for whatever reason couldn't use set-
  460. 17:01e for a command like false which will
  461. 17:03fail we can use the or the double pipe
  462. 17:07and just say exit one so if that fails
  463. 17:11then we'll immediately exit the program
  464. 17:13as we'd expect but better is to use set-
  465. 17:16e and then in this case if we have a
  466. 17:18command like false which we know is
  467. 17:19going to fail but we want the program to
  468. 17:21continue anyway we can do this where we
  469. 17:24or that with true so if false encounters
  470. 17:27an issue then we'll run true and true is
  471. 17:29going to be a success so it'll carry on
  472. 17:32so without set- youu you'll often
  473. 17:34encounter this problem where you
  474. 17:36reference a variable like name in this
  475. 17:38case where name was never actually
  476. 17:40defined and the result is it'll just
  477. 17:43print nothing in that spot but the
  478. 17:45script will continue on but the reality
  479. 17:47is you probably because you referenced
  480. 17:49it you probably wanted name to exist you
  481. 17:51were hoping that something was there and
  482. 17:53so if you do set- U this will have it so
  483. 17:57it exits on the case of referencing
  484. 17:59something that's undefined at that point
  485. 18:01so this will help you catch a lot of
  486. 18:03minor bugs where either you typo
  487. 18:05something or you thought that you
  488. 18:06declared something up above and you
  489. 18:08didn't always good to have and then set-
  490. 18:11o pipe fail we're going to use set- e
  491. 18:13with this to make this easier to
  492. 18:16understand if you run something like
  493. 18:17false which again fails and then you
  494. 18:19have that as part of a pipeline where
  495. 18:21the next step runs and that succeeds the
  496. 18:25false at the beginning the failure
  497. 18:26actually gets lost and so even though we
  498. 18:28have set- e and the program should exit
  499. 18:30when something fails it's going to
  500. 18:32continue on anyway cuz it's how the echo
  501. 18:34hello was a success whereas if we
  502. 18:36introduce the- o pipe fail it will
  503. 18:39detect that first error the false where
  504. 18:42it fails and then the script itself will
  505. 18:45exit that's again much better Behavior
  506. 18:48you don't want to lose errors in a
  507. 18:50pipeline so in general I would always
  508. 18:53add this set- EO pipe fail right below
  509. 18:56your shebang all right all right so at
  510. 18:58this point we've actually covered
  511. 19:00probably 80% of everything that you're
  512. 19:01going to need to know but as I mentioned
  513. 19:03there's a lot of the language that I've
  514. 19:05never even used and I've written a ton
  515. 19:06of bash scripts so I'm going to show you
  516. 19:08the things that you're likely to
  517. 19:09encounter at some point probably not in
  518. 19:11every script but in some so arrays
  519. 19:15sometimes you need to create a list of
  520. 19:16items so in this case I'm creating an
  521. 19:19array of numbers and the syntax honestly
  522. 19:21a little bit confusing so it looks like
  523. 19:23a subshell but it's not when you do the
  524. 19:25variable assignment with the parentheses
  525. 19:27here each item and it needs to be
  526. 19:29separated by spaces but these are going
  527. 19:31to be separate items in the array and
  528. 19:33then to access them if you want to
  529. 19:35access a particular item in that array
  530. 19:37you can use the index like this where we
  531. 19:39have the square brackets and the index
  532. 19:41number you can also refer to all the
  533. 19:43elements if you're doing the square
  534. 19:45brackets if you do the at sign that's
  535. 19:48going to reference all of them or you
  536. 19:49could just leave off the square brackets
  537. 19:51and just do my array and that would also
  538. 19:53work and again we can do other things
  539. 19:56like using the hash to print out the
  540. 19:58length of the array so the number of
  541. 20:00items we've also got four Loops which
  542. 20:03bash actually has a surprisingly good
  543. 20:05variety of four Loops here so you've got
  544. 20:07a pretty standard one here where we've
  545. 20:08got four item in my array and so this
  546. 20:11will Loop through each element from my
  547. 20:13array here and you'll see the syntax
  548. 20:15here is do and done so everything within
  549. 20:18that block will be done for each item
  550. 20:20there we go as expected it just prints
  551. 20:22out the numbers but it also has a cstyle
  552. 20:25version so you can do the classic I
  553. 20:27equal Z I is less than whatever i++ you
  554. 20:31can do things like that a more compact
  555. 20:33version is with the range so 4 I and and
  556. 20:36you can say I dot dot whatever number
  557. 20:38you want so here's an interesting one
  558. 20:40where you can do pattern matching so you
  559. 20:42can set a pattern like this where I'm
  560. 20:44looking at all of the markdown files
  561. 20:46within the content directory we've also
  562. 20:48got command results so you can run
  563. 20:50something like LS which will return a
  564. 20:52list of items and then we'll Loop
  565. 20:54through each item in that output so a
  566. 20:57pretty good r iy there of course there
  567. 20:59are also while Loops I don't find myself
  568. 21:01using these all that often but the
  569. 21:03syntax is pretty straightforward while
  570. 21:05condition do done one little Oddity here
  571. 21:08is again due to the weird way that math
  572. 21:10Works in bash to increment the counter
  573. 21:13here you need to do it in those double
  574. 21:15parentheses but we get the same result
  575. 21:17as we'd expect now the one use case that
  576. 21:19I do find myself using while Loops for
  577. 21:21quite a bit is for what I call wait
  578. 21:23until true so in this case I'm going
  579. 21:25through an example where I deploy some
  580. 21:27application to kubernetes cluster and I
  581. 21:29wait until it's up into a running state
  582. 21:31so we've got an infinite Loop here so
  583. 21:33while true do the following and so first
  584. 21:36we'll save some status so in this case
  585. 21:38I'm getting the Pod status in a subshell
  586. 21:41and we're getting that output it'll look
  587. 21:43something like starting up or running or
  588. 21:46whatever in this case I'm waiting till
  589. 21:48the status is equal to running and as
  590. 21:51soon as that matches I'm going to break
  591. 21:52out of the infinite Loop otherwise we'll
  592. 21:55go into this else block and it'll print
  593. 21:57out some logging statement and then
  594. 21:59it'll bring back that sleep that we
  595. 22:01talked about earlier all right another
  596. 22:03situation you'll encounter at some point
  597. 22:04if you're writing a long script is that
  598. 22:06things get a bit complicated to
  599. 22:08understand you know it's just not
  600. 22:09pleasant to work with so you can break
  601. 22:11it out into multiple files now should be
  602. 22:14noted that bash has no concept of
  603. 22:16namespacing or modules or anything like
  604. 22:18that it's just separate files and so
  605. 22:21here we've got a setup here where we've
  606. 22:23got this provisioner Dosh which will
  607. 22:25pretend is provisioning some new vir
  608. 22:28machine and then it's going to configure
  609. 22:30some DNS records and so on so we've got
  610. 22:32an instance. sh which will handle the
  611. 22:34provisioning of the virtual machine got
  612. 22:36the DNS file that will actually update
  613. 22:39the DNS records and the provisioner dosh
  614. 22:42will kick off each of those in their
  615. 22:44turn so calling out to those different
  616. 22:46scripts as we can see is just like
  617. 22:48running any other command except we're
  618. 22:51doing it as a relative path rather than
  619. 22:53a command but just like anything else
  620. 22:56from the command line we can pass
  621. 22:58arguments right so we could in each of
  622. 23:00these scripts have the relevant
  623. 23:03variables for those like the region and
  624. 23:05the size for the instance and the domain
  625. 23:07name for the DNS but there are two ways
  626. 23:09of actually doing this so you can Source
  627. 23:12a shell script or you can kick it off
  628. 23:14execute it in a subshell so sourcing is
  629. 23:17kind of interesting where it's going to
  630. 23:20operate in the same shell so here's an
  631. 23:22example of how this works so if I set my
  632. 23:24favorite color is equal to green and
  633. 23:26then I Echo that we can see the output
  634. 23:27is green then I Source it using this Dot
  635. 23:31and then the script with the space in
  636. 23:33between there that's saying Source this
  637. 23:35script that will load it up and so now
  638. 23:38when we Echo favorite color it's still
  639. 23:40green then if I set favorite color to
  640. 23:43blue and then Echo that we get blue but
  641. 23:45then back in script one if I Echo
  642. 23:47favorite color we get blue and that's
  643. 23:49because if we think about how the source
  644. 23:51will work it's effectively taking all
  645. 23:54the contents of script 2 and just
  646. 23:56dumping them in line into script script
  647. 23:58one exactly where the call to script 2
  648. 24:01is so that means that we're using the
  649. 24:03same shell all the variables are the
  650. 24:05same and it's all just a way of breaking
  651. 24:08things out so that makes it easy to
  652. 24:10carry on all the continuity with
  653. 24:13everything without having to pass around
  654. 24:14values so in some cases this is quite
  655. 24:16handy the other way is the subshell
  656. 24:18where if we do favorite color is green
  657. 24:21once I call it to script two without
  658. 24:23using the source this is just executing
  659. 24:25the script this now spins up in a
  660. 24:27subshell
  661. 24:28and when it runs Echo favorite color it
  662. 24:30actually has no idea what favorite color
  663. 24:31is cuz it hasn't been declared yet and
  664. 24:33if we had set- set it would have exited
  665. 24:36the program because it would say hey we
  666. 24:38have no idea what this is but once I
  667. 24:40declare favorite colors blue and print
  668. 24:41that it's cool with that and then back
  669. 24:43to script one favorite color as far as
  670. 24:46its wear is still green so we can see
  671. 24:48those operate very differently so the
  672. 24:50question is which one should you be
  673. 24:52using and it really comes down to both
  674. 24:54personal preference and the specific use
  675. 24:56case I like to default to using the
  676. 24:58subshell version because I don't like to
  677. 25:01have all these implicit references
  678. 25:03everywhere I would prefer to pass in
  679. 25:05exactly what a script needs just like
  680. 25:07with functions you don't want to be
  681. 25:08referencing Global variables you really
  682. 25:10want to be passing in everything it
  683. 25:12needs and so it's more self
  684. 25:14enclosed that being said because the
  685. 25:16context of most scripts is very tightly
  686. 25:19coupled you know you're not trying to
  687. 25:21break stuff out to make it more reusable
  688. 25:23you're doing it just so it's easier to
  689. 25:25comprehend sourcing can be just fine and
  690. 25:27it'll save you from having to redeclare
  691. 25:29variables but the choice is yours you
  692. 25:32might notice that we haven't talked
  693. 25:33about functions yet and pretty much
  694. 25:36every language that you use you're going
  695. 25:37to be using functions a lot so it's kind
  696. 25:40of strange to not have touched on it yet
  697. 25:42but in truth I really don't use
  698. 25:44functions at all in bash save for a few
  699. 25:48situations and you'll see why in a
  700. 25:50second our function signature is
  701. 25:52function and then the name parenthesis
  702. 25:54and then we've got squiggly brackets
  703. 25:57absent you might notice is we don't have
  704. 25:59any arguments within the parenthesis
  705. 26:01that's one of the peculiarities of bash
  706. 26:03it's going to take in whatever is past
  707. 26:05into the function and then we can choose
  708. 26:07to do with it what we want now do note
  709. 26:10that when we're looking at the one and
  710. 26:11two variables here this is actually
  711. 26:14totally separate from The Wider script
  712. 26:16so you could have one and two at the
  713. 26:18global level but the one and two here is
  714. 26:21scoped to within this function call
  715. 26:23confusingly notice that we've got the
  716. 26:25local tool and local install URLs here
  717. 26:27that's because if we just declared the
  718. 26:29variables tool and install URL without
  719. 26:32specifying them as local they would
  720. 26:34actually be declaring them globally not
  721. 26:36locally to the function scope so kind of
  722. 26:38confusing that that behavior between
  723. 26:41those two isn't consistent but that's
  724. 26:43the way that it is so just got to deal
  725. 26:44with it but within the function you can
  726. 26:47do whatever you want you'll notice that
  727. 26:49the way that it works is very similar to
  728. 26:52a script so when we call out to it it's
  729. 26:54just like any other script or command so
  730. 26:56we can say insure dependen y passing in
  731. 26:58the arguments that we want no
  732. 27:00parentheses no nothing like that and the
  733. 27:01reason that I don't end up using this a
  734. 27:03lot say for instances like this or just
  735. 27:06have some small thing that I want to
  736. 27:07repeat over and over again is because
  737. 27:10the types of things you do in bass
  738. 27:11scripting tend to be relying on external
  739. 27:14tools and so any shared logic would be
  740. 27:17already pre-built into that then in
  741. 27:18other languages like let's say you're
  742. 27:20using python you really don't want to
  743. 27:22have a single function that does like 15
  744. 27:24things you're going to want to break
  745. 27:25those into separate functions even if
  746. 27:27you're only going to use them once but
  747. 27:30there isn't a huge amount of benefit to
  748. 27:31doing that within bash a quick little
  749. 27:34tip here is you might find yourself
  750. 27:36frequently I know that I have when I'm
  751. 27:38doing infrastructure stuff where I'm
  752. 27:39creating files and want to clean them up
  753. 27:42later there's this tool called M temp
  754. 27:45where if you do that from within a
  755. 27:47subshell it'll create a file inside of a
  756. 27:51temporary directory and then it'll
  757. 27:53reference that so you can assign some
  758. 27:55new variable to whatever the output is
  759. 27:57and then you can treat that just like
  760. 27:59any other file you have no idea where
  761. 28:01this file actually exists it's going to
  762. 28:02be likely in slm slash some random
  763. 28:05string and because it's in the temp
  764. 28:07directory it'll get cleaned up
  765. 28:09automatically at some point by your
  766. 28:10system but you can do this in
  767. 28:12combination with this trap command which
  768. 28:14will execute some given command in this
  769. 28:17case we're removing the temp file on a
  770. 28:19given signal and the signal we're
  771. 28:21looking for is exit so as soon as the
  772. 28:24script completes we get the exit signal
  773. 28:27in this command will be run the temp
  774. 28:28file will be cleaned up automatically so
  775. 28:30I find that very helpful and you can do
  776. 28:32the same thing for directories using
  777. 28:34make temp DD and then you can do
  778. 28:37whatever you want inside of that
  779. 28:38temporary directory and you can know
  780. 28:40that as soon as the script is completed
  781. 28:42all of that will be wiped automatically
  782. 28:44another quick thing to discuss is the
  783. 28:46naming Convention of the script
  784. 28:48themselves so do you do something like
  785. 28:50provision. sh or do you just call it
  786. 28:52provisioner and there's no strict rule
  787. 28:55around this but the way that I see it I
  788. 28:56like to do for anything that's like
  789. 28:58local to a project I'm going to use the
  790. 29:00dosh so it's very clear what this thing
  791. 29:02even is we know that it's a script but
  792. 29:05if I want it to be systemwide like a
  793. 29:07command that would run from anywhere in
  794. 29:09the system I'm just going to use
  795. 29:10provisioner in this case not provisioner
  796. 29:12Dosh because I don't care if provisioner
  797. 29:15is a script or if it's some binary or
  798. 29:17anything else I just know that I want
  799. 29:19this to run so that's how I look at it
  800. 29:22when you're trying to treat things like
  801. 29:23commands it's important to understand
  802. 29:25the path so if I was to call a command
  803. 29:28say we've got a command called blackout
  804. 29:30which will set my machine to night mode
  805. 29:32ordinarily you're going to call it with
  806. 29:34its file path so if it's in the current
  807. 29:36directory it'll look like this where
  808. 29:38it's do/ blackout you can also do
  809. 29:40absolute path but if I call it just
  810. 29:43blackout my shell is going to say hey I
  811. 29:46have no idea what that is and the reason
  812. 29:48for that is blackout doesn't happen to
  813. 29:50be in the path so what is the path well
  814. 29:53the path is an environment variable
  815. 29:55that's set in your shell that that lets
  816. 29:58it know exactly what directories to
  817. 30:00search in whenever it's looking for a
  818. 30:01command so it'll look something like
  819. 30:03this where we've got a series of
  820. 30:04directories they'll be separated by
  821. 30:07colons and whenever you run a command
  822. 30:10your shell will check across all of
  823. 30:12these directories and figure out which
  824. 30:15one actually contains that particular
  825. 30:18command and if that command doesn't
  826. 30:20happen to be found in any of those
  827. 30:21directories we'll get that command not
  828. 30:22found error so how do we Ramy that we've
  829. 30:26probably actually done this before many
  830. 30:28times you might not have been aware of
  831. 30:30what it's doing but there's this export
  832. 30:32path command that you'll run where you
  833. 30:33set the path to the current value the
  834. 30:35path and then you do colon and then you
  835. 30:37add on whatever new directory you want
  836. 30:39so I like to use a do scripts directory
  837. 30:42that lives in the home directory and I
  838. 30:43dump all my scripts in there you can do
  839. 30:45wherever you want but just remember that
  840. 30:47you need to export that in order to make
  841. 30:50them all accessible to your system but
  842. 30:52once you've run that now anywhere within
  843. 30:54that shell you can run blackout it
  844. 30:55doesn't matter if you're in the scripts
  845. 30:56directory or anywhere else it'll run
  846. 30:59just fine but that is only for the
  847. 31:01duration of that shell session so make
  848. 31:03sure to add your export path command to
  849. 31:06your Shell's configuration file so like
  850. 31:08your bash RC so with that we've covered
  851. 31:10everything that you need to know but I'm
  852. 31:12going to quickly walk you through the
  853. 31:14general process I go through whenever I
  854. 31:16create a new script so first and
  855. 31:17foremost you need to have some idea of
  856. 31:19what you're trying to do not really
  857. 31:21point in writing a script if you don't
  858. 31:22know what you're trying to solve but
  859. 31:23once you have that then you identify
  860. 31:26what tool you want to use
  861. 31:27the majority of what you're going to be
  862. 31:28doing in your actual script is just
  863. 31:31glooming together all these powerful
  864. 31:33tools that already purpose-built for
  865. 31:35some use case and you're just trying to
  866. 31:37glue them into some particular pattern
  867. 31:39that solves your problem so you figure
  868. 31:41out what tools you're going to be using
  869. 31:43and then you sketch it out in the
  870. 31:44terminal so you just do it manually run
  871. 31:47the commands and just play around until
  872. 31:49you figure out exactly what you want it
  873. 31:50to do from there you can then copy all
  874. 31:53those commands you can use history to
  875. 31:55pull all those commands out but grab
  876. 31:57them into a script from there you then
  877. 32:00parameterize it so pull out anything
  878. 32:02that will change between different runs
  879. 32:05and then create command line arguments
  880. 32:06and all that add some checks so if there
  881. 32:09are things that you need to make sure
  882. 32:11they're passed in or to make sure that
  883. 32:13files exist and so on you can add guard
  884. 32:15Clauses and all that and I say that at
  885. 32:17that point the majority of my scripts
  886. 32:19are done but sometimes things need to
  887. 32:21get more complex and so you'll have more
  888. 32:23advanced logic you might have loops you
  889. 32:25might have functions so you can add
  890. 32:27those in as necessary but I generally
  891. 32:29like to have all of this starting in a
  892. 32:31single file but then if things get too
  893. 32:34large then I break it into multiple
  894. 32:36files so quickly if we take a look at
  895. 32:38this process with an example the FFM P
  896. 32:41example I know that I wanted to create a
  897. 32:43script that will merge a video file and
  898. 32:45an audio file into a single output so I
  899. 32:48know that I'm going to use FFM Peg for
  900. 32:49this it's very good at that and so I can
  901. 32:53sketch it out I can run this ugly
  902. 32:54command to get it to work but now that I
  903. 32:57have this I'll just dump that directly
  904. 32:58into a script but we can see it's
  905. 33:00hardcoded with all these values like
  906. 33:03video. MP4 so I'll pull those out into
  907. 33:05variables and use commandline arguments
  908. 33:08so with that in place things are pretty
  909. 33:10good but let's add some checks so I want
  910. 33:14to make sure that I actually have three
  911. 33:15command line arguments because this
  912. 33:17would fail if I only passed in two so
  913. 33:20we'll print out a usage error and exit
  914. 33:23if not all that set but with that we're
  915. 33:25done with the fmeg example you could add
  916. 33:27additional checks like you could make
  917. 33:29sure that those files exist but for
  918. 33:31simple things like this I wouldn't
  919. 33:32bother another quick example so I work a
  920. 33:36lot with kubernetes so I like to be able
  921. 33:39to spin up local kubernetes clusters
  922. 33:41easily and I want to install some apps
  923. 33:43in them so the tools that I'm going to
  924. 33:46use are kind to provision the Clusters
  925. 33:49Cube control to interact with the
  926. 33:50cluster and Helm to install applications
  927. 33:53so if I sketch it out I'll run some
  928. 33:54commands like this or I'll run kind to
  929. 33:58create the cluster I'll run some Helm
  930. 34:00commands to add the repositories and do
  931. 34:03the upgrade and install and then at the
  932. 34:05end I'll use keepy control to port
  933. 34:07forward pretty simple example but I can
  934. 34:09dump that into a script and actually as
  935. 34:11it stands this could run just fine
  936. 34:13without any parameters or anything but
  937. 34:16there are things that we could
  938. 34:17parameterize like the cluster Name by
  939. 34:19doing this now I can support multiple
  940. 34:21clusters at once but I can still default
  941. 34:23to using just the playground name if I
  942. 34:26want to
  943. 34:27then I can add some checks right I need
  944. 34:29to make sure that these tools are
  945. 34:30actually available on my machine so kind
  946. 34:33Helm and Cube control this is the point
  947. 34:34where I'd figure out that hey actually
  948. 34:36this is very repetitive and I could pull
  949. 34:38this into a function like we saw this
  950. 34:41function previously to ensure
  951. 34:42dependencies and now I can reference
  952. 34:45those and I could as I grow and include
  953. 34:47more tools I can easily ensure that
  954. 34:49they're all available and obviously the
  955. 34:52script could keep growing it could do a
  956. 34:53lot more stuff so the general process
  957. 34:55again is just do the stuff manually and
  958. 34:57then iterate I think the worst thing you
  959. 34:59can do is try to write the entire script
  960. 35:02in one go and then only test it at the
  961. 35:04end I think just due to the nice nature
  962. 35:08of working with a shell language just
  963. 35:09like with python or JavaScript where we
  964. 35:11can use the reppel to play around and
  965. 35:13try things out because everything you
  966. 35:15write is the same as within the terminal
  967. 35:18there's no reason to not try things out
  968. 35:20manually and then dump them into the
  969. 35:21script once they're working all right so
  970. 35:24I've covered a whole lot there's more to
  971. 35:26the language and there's this great site
  972. 35:28called learn xiny minutes.com I'll link
  973. 35:30it down below but they've got a great
  974. 35:32guide on bash and pretty much any
  975. 35:34language that you should definitely
  976. 35:36check out that brings us to the end so I
  977. 35:39hope this has been helpful I hope that
  978. 35:40you go out there and write some bash
  979. 35:42scripts that save you a bunch of time
  980. 35:43and that you now have superpowers that
  981. 35:45will impress others as you can see bash
  982. 35:47is you know it's an awkward language in
  983. 35:50many ways but it's very powerful just
  984. 35:52due to the nature of calling out to all
  985. 35:54these other commands so thanks for
  986. 35:57watching and I will see you in the next
  987. 35:58one

About this transcript

This page contains the full transcript of Become a bash scripting pro - full course by Terminal Velocity, generated from the public captions YouTube serves with the video. The transcript has 7,336 words across 987 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.

What you can do with it

Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.

Free YouTube transcript tool

YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.