You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 04-Bash-Scripting.md
+32-37Lines changed: 32 additions & 37 deletions
Original file line number
Diff line number
Diff line change
@@ -4,10 +4,10 @@
4
4
5
5
In addition to being a fully-functional[^functional] interactive shell, Bash can also run commands from a text file (known as a 'shell script').
6
6
It even includes conditionals and loops!
7
-
These scripts are the duct tape and bailing wire of computer programming -- great for connecting other programs together.
7
+
These scripts are the duct tape and bailing wire of computer programming --- great for connecting other programs together.
8
8
Use shell scripts to write one-off tools for odd jobs, to build utilities that make your life easier, and to customize your shell.
9
9
10
-
**Note**: There's nothing special about the contents of a shell script -- everything you learn in this lab you could type into the Bash prompt itself.
10
+
**Note**: There's nothing special about the contents of a shell script --- everything you learn in this lab you could type into the Bash prompt itself.
11
11
12
12
### Takeaways
13
13
@@ -17,7 +17,7 @@ Use shell scripts to write one-off tools for odd jobs, to build utilities that m
17
17
## Walkthrough
18
18
19
19
Here's a quick example of what a shell script looks like:
20
-
```bash
20
+
```{.bash .numberLines}
21
21
#!/bin/bash
22
22
23
23
g++ *.cpp
@@ -29,7 +29,7 @@ To run it, put it in a file named, say, `runit1.sh`, then type `./runit1.sh`[^pa
29
29
30
30
Two things to note:
31
31
32
-
1. The first line, called a "shebang"[^shebang], tells Bash what program to run the script through. In this case, it's a Bash script.
32
+
1. The first line, called a "shebang",[^shebang] tells Bash what program to run the script through. In this case, it's a Bash script.
33
33
2. The rest of the file is a sequence of commands, one per line, just as you would type them into the shell.
34
34
35
35
For simple scripts, this may be all you need!
@@ -45,7 +45,7 @@ Let's check out some of those features and use them to improve this example.
45
45
There's no special keyword for declaring variables; you just define what you want them to be.
46
46
When you use them, you must prefix the variable name with a `$`:
47
47
48
-
```bash
48
+
```{.bash .numberLines}
49
49
#!/bin/bash
50
50
51
51
# Assign the value "big" to the variable COW
@@ -84,7 +84,7 @@ $ echo $?
84
84
85
85
Bash also provides variables holding the command-line arguments passed to the script.
86
86
A command-line argument is something that you type after the command; for instance, in the command `ls /tmp`, `/tmp` is the first argument passed to `ls`.
87
-
The name of the command that started the script is stored in `$0`. This is almost always just the name of the script[^symlinks].
87
+
The name of the command that started the script is stored in `$0`. This is almost always just the name of the script.[^symlinks]
88
88
The variables `$1` through `$9` contain the first through ninth command line arguments, respectively.
89
89
To get the 10th argument, you have to write `${10}`, and likewise for higher argument numbers.
90
90
@@ -108,7 +108,7 @@ So as a rule, rather than `$1`, use `"$1"`, and iterate over `"$@"` rather than
108
108
109
109
We can spiff up our example to allow the user to set the name of the executable to be produced:
110
110
111
-
```bash
111
+
```{.bash .numberLines}
112
112
#!/bin/bash
113
113
114
114
g++ *.cpp -o "$1"
@@ -126,11 +126,11 @@ If the command succeeds (i.e., returns 0), the body of the if statement is execu
126
126
127
127
Bash provides some handy commands for writing common conditional expressions:
128
128
`[ ]` is shorthand for the `test` command, and `[[ ]]` is a Bash builtin.
129
-
`[ ]` works on shells other than Bash, but `[[ ]]` is far less confusing[^portability].
129
+
`[ ]` works on shells other than Bash, but `[[ ]]` is far less confusing.[^portability]
130
130
131
131
Here's an example of how to write `if` statements in Bash:
132
132
133
-
```bash
133
+
```{.bash .numberLines}
134
134
#!/bin/bash
135
135
136
136
# Emit the appropriate greeting for various people
@@ -153,7 +153,7 @@ Be careful not to forget the semicolon after the condition or the `fi` at the en
153
153
#### Writing conditionals with `[[ ]]`
154
154
155
155
Since Bash is dynamically typed, `[[ ]]` has one set of operators for comparing strings and another set for comparing numbers.
156
-
That way, you can specify which type of comparison to use, rather than hoping that Bash guesses right[^javascript2].
156
+
That way, you can specify which type of comparison to use, rather than hoping that Bash guesses right.[^javascript2]
157
157
158
158
Comparing Strings:
159
159
@@ -189,7 +189,7 @@ Checking Attributes of Files:
189
189
190
190
Here's an example that, given a directory, lists the files in it; and given a file, prints the contents of the file:
191
191
192
-
```bash
192
+
```{.bash .numberLines}
193
193
#!/bin/bash
194
194
195
195
# First, check to make sure we got an argument
@@ -218,7 +218,7 @@ Boolean Logic:
218
218
219
219
You can also group statements using parentheses:
220
220
221
-
```bash
221
+
```{.bash .numberLines}
222
222
#!/bin/bash
223
223
224
224
num=5
@@ -238,7 +238,7 @@ fi
238
238
239
239
When working with `(( ))`, you do not need to prefix variable names with `$`:
240
240
241
-
```bash
241
+
```{.bash .numberLines}
242
242
#!/bin/bash
243
243
244
244
x=5
@@ -252,11 +252,11 @@ fi
252
252
253
253
#### Case statements
254
254
255
-
Case statements in Bash work similar to the `==` operator for `[[ ]]`; you can make cases for strings and globs.
255
+
Case statements in Bash work similar to the `==` operator for `[[ ]]`: you can make cases for strings and globs.
256
256
257
257
Here is an example case statement:
258
258
259
-
```bash
259
+
```{.bash .numberLines}
260
260
#!/bin/bash
261
261
262
262
case$1in
@@ -278,7 +278,7 @@ case $1 in
278
278
esac
279
279
```
280
280
281
-
Do not forget the double semicolon at the end of each case -- `;;` is *required* to end a case.
281
+
Do not forget the double semicolon at the end of each case ---`;;` is *required* to end a case.
282
282
They are analogous to `break` in C++; bash case statements do not have fallthrough.
283
283
284
284
As with `if`, `case` statements end with `esac`.
@@ -288,7 +288,7 @@ As with `if`, `case` statements end with `esac`.
288
288
We can use conditional statements to spiff up our previous `runit2.sh` script.
289
289
This example demonstrates numeric comparison using both `(( ))` and `[[ ]]`.
290
290
291
-
```bash
291
+
```{.bash .numberLines}
292
292
#!/bin/bash
293
293
294
294
# If the user specifies an executable name, use that name;
@@ -315,7 +315,7 @@ Can you make this example even spiffier using file attribute checks?
315
315
Inside `(( ))`, you do not need to prefix variable names with `$`!
316
316
317
317
For example,
318
-
```bash
318
+
```{.bash .numberLines}
319
319
#!/bin/bash
320
320
321
321
x=5
@@ -337,7 +337,7 @@ Bash for loops typically follow a pattern of looping over the contents of an arr
337
337
338
338
For (heh) example, you can print out the names of all `.sh` files in the current directory like so:
339
339
340
-
```bash
340
+
```{.bash .numberLines}
341
341
#!/bin/bash
342
342
343
343
forfilein*.sh;do
@@ -347,7 +347,7 @@ done
347
347
348
348
Or sum all command-line arguments:
349
349
350
-
```bash
350
+
```{.bash .numberLines}
351
351
#!/bin/bash
352
352
353
353
sum=0
@@ -361,7 +361,7 @@ echo $sum
361
361
362
362
If you need a counting for loop (C-style loop), you can get one of those with `(( ))`:
363
363
364
-
```bash
364
+
```{.bash .numberLines}
365
365
#!/bin/bash
366
366
367
367
for(( i=1; i <9; i++));do
@@ -379,7 +379,7 @@ As with for loops, the loop body is enclosed between `do` and `done`.
379
379
Any conditional you'd use with an if statement will also work with a while loop.
380
380
381
381
For example,
382
-
```bash
382
+
```{.bash .numberLines}
383
383
#!/bin/bash
384
384
385
385
input=""
@@ -401,7 +401,7 @@ Furthermore, they can only return an error code; "returning" other values requir
401
401
402
402
Here's a simple function example:
403
403
404
-
```bash
404
+
```{.bash .numberLines}
405
405
#!/bin/bash
406
406
407
407
# Declare a function named 'parrot'
@@ -420,7 +420,7 @@ parrot These are "several arguments"
420
420
421
421
To return something, the easiest solution is to `echo` it and have the caller catch the value:
422
422
423
-
```bash
423
+
```{.bash .numberLines}
424
424
#!/bin/bash
425
425
426
426
average() {
@@ -442,7 +442,7 @@ Here, `my_average=$(average 1 2 3 4)` calls `average` with the arguments `1 2 3
442
442
443
443
One word of warning: in Bash, all variables are globally scoped by default, so it is easy to accidentally clobber a variable:
444
444
445
-
```bash
445
+
```{.bash .numberLines}
446
446
#!/bin/bash
447
447
448
448
# create a bunch of files with "hello" in them
@@ -467,9 +467,9 @@ You can scope variables to functions with the `local` builtin; run `help local`
467
467
468
468
### Tips
469
469
470
-
To write a literal ``\ , `, $, ", ’, #``, escape it with `\`; for instance, `"\$"` gives a literal `$`.
470
+
To write a literal `\` , `` ` ``, `$`, `"`, `'`, or `#`, escape it with `\`; for instance, `"\$"` gives a literal `$`.
471
471
472
-
When writing scripts, sometimes you will want to change directories -- for instance, maybe you want to write some temporary files in `/tmp`.
472
+
When writing scripts, sometimes you will want to change directories --- for instance, maybe you want to write some temporary files in `/tmp`.
473
473
Rather than using `cd` and keeping track of where you were so you can `cd` back later, use `pushd` and `popd`.
474
474
`pushd` pushes a new directory onto the directories stack and `popd` removes a directory from this stack.
475
475
Use `dirs` to print out the stack.
@@ -528,7 +528,8 @@ This list is stored in the `$PATH` variable; the list of directories is delimite
0 commit comments