Skip to content

Commit 0561a68

Browse files
committed
edits and line numbering
1 parent 4048a12 commit 0561a68

File tree

1 file changed

+32
-37
lines changed

1 file changed

+32
-37
lines changed

04-Bash-Scripting.md

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
In addition to being a fully-functional[^functional] interactive shell, Bash can also run commands from a text file (known as a 'shell script').
66
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.
88
Use shell scripts to write one-off tools for odd jobs, to build utilities that make your life easier, and to customize your shell.
99

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.
1111

1212
### Takeaways
1313

@@ -17,7 +17,7 @@ Use shell scripts to write one-off tools for odd jobs, to build utilities that m
1717
## Walkthrough
1818

1919
Here's a quick example of what a shell script looks like:
20-
```bash
20+
```{.bash .numberLines}
2121
#!/bin/bash
2222

2323
g++ *.cpp
@@ -29,7 +29,7 @@ To run it, put it in a file named, say, `runit1.sh`, then type `./runit1.sh`[^pa
2929

3030
Two things to note:
3131

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.
3333
2. The rest of the file is a sequence of commands, one per line, just as you would type them into the shell.
3434

3535
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.
4545
There's no special keyword for declaring variables; you just define what you want them to be.
4646
When you use them, you must prefix the variable name with a `$`:
4747

48-
```bash
48+
```{.bash .numberLines}
4949
#!/bin/bash
5050

5151
# Assign the value "big" to the variable COW
@@ -84,7 +84,7 @@ $ echo $?
8484

8585
Bash also provides variables holding the command-line arguments passed to the script.
8686
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]
8888
The variables `$1` through `$9` contain the first through ninth command line arguments, respectively.
8989
To get the 10th argument, you have to write `${10}`, and likewise for higher argument numbers.
9090

@@ -108,7 +108,7 @@ So as a rule, rather than `$1`, use `"$1"`, and iterate over `"$@"` rather than
108108

109109
We can spiff up our example to allow the user to set the name of the executable to be produced:
110110

111-
```bash
111+
```{.bash .numberLines}
112112
#!/bin/bash
113113

114114
g++ *.cpp -o "$1"
@@ -126,11 +126,11 @@ If the command succeeds (i.e., returns 0), the body of the if statement is execu
126126

127127
Bash provides some handy commands for writing common conditional expressions:
128128
`[ ]` 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]
130130

131131
Here's an example of how to write `if` statements in Bash:
132132

133-
```bash
133+
```{.bash .numberLines}
134134
#!/bin/bash
135135

136136
# 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
153153
#### Writing conditionals with `[[ ]]`
154154

155155
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]
157157

158158
Comparing Strings:
159159

@@ -189,7 +189,7 @@ Checking Attributes of Files:
189189

190190
Here's an example that, given a directory, lists the files in it; and given a file, prints the contents of the file:
191191

192-
```bash
192+
```{.bash .numberLines}
193193
#!/bin/bash
194194

195195
# First, check to make sure we got an argument
@@ -218,7 +218,7 @@ Boolean Logic:
218218

219219
You can also group statements using parentheses:
220220

221-
```bash
221+
```{.bash .numberLines}
222222
#!/bin/bash
223223

224224
num=5
@@ -238,7 +238,7 @@ fi
238238

239239
When working with `(( ))`, you do not need to prefix variable names with `$`:
240240

241-
```bash
241+
```{.bash .numberLines}
242242
#!/bin/bash
243243

244244
x=5
@@ -252,11 +252,11 @@ fi
252252

253253
#### Case statements
254254

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.
256256

257257
Here is an example case statement:
258258

259-
```bash
259+
```{.bash .numberLines}
260260
#!/bin/bash
261261

262262
case $1 in
@@ -278,7 +278,7 @@ case $1 in
278278
esac
279279
```
280280

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.
282282
They are analogous to `break` in C++; bash case statements do not have fallthrough.
283283

284284
As with `if`, `case` statements end with `esac`.
@@ -288,7 +288,7 @@ As with `if`, `case` statements end with `esac`.
288288
We can use conditional statements to spiff up our previous `runit2.sh` script.
289289
This example demonstrates numeric comparison using both `(( ))` and `[[ ]]`.
290290

291-
```bash
291+
```{.bash .numberLines}
292292
#!/bin/bash
293293

294294
# 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?
315315
Inside `(( ))`, you do not need to prefix variable names with `$`!
316316

317317
For example,
318-
```bash
318+
```{.bash .numberLines}
319319
#!/bin/bash
320320

321321
x=5
@@ -337,7 +337,7 @@ Bash for loops typically follow a pattern of looping over the contents of an arr
337337

338338
For (heh) example, you can print out the names of all `.sh` files in the current directory like so:
339339

340-
```bash
340+
```{.bash .numberLines}
341341
#!/bin/bash
342342

343343
for file in *.sh; do
@@ -347,7 +347,7 @@ done
347347

348348
Or sum all command-line arguments:
349349

350-
```bash
350+
```{.bash .numberLines}
351351
#!/bin/bash
352352

353353
sum=0
@@ -361,7 +361,7 @@ echo $sum
361361

362362
If you need a counting for loop (C-style loop), you can get one of those with `(( ))`:
363363

364-
```bash
364+
```{.bash .numberLines}
365365
#!/bin/bash
366366

367367
for (( i=1; i < 9; i++ )); do
@@ -379,7 +379,7 @@ As with for loops, the loop body is enclosed between `do` and `done`.
379379
Any conditional you'd use with an if statement will also work with a while loop.
380380

381381
For example,
382-
```bash
382+
```{.bash .numberLines}
383383
#!/bin/bash
384384

385385
input=""
@@ -401,7 +401,7 @@ Furthermore, they can only return an error code; "returning" other values requir
401401

402402
Here's a simple function example:
403403

404-
```bash
404+
```{.bash .numberLines}
405405
#!/bin/bash
406406

407407
# Declare a function named 'parrot'
@@ -420,7 +420,7 @@ parrot These are "several arguments"
420420

421421
To return something, the easiest solution is to `echo` it and have the caller catch the value:
422422

423-
```bash
423+
```{.bash .numberLines}
424424
#!/bin/bash
425425

426426
average() {
@@ -442,7 +442,7 @@ Here, `my_average=$(average 1 2 3 4)` calls `average` with the arguments `1 2 3
442442

443443
One word of warning: in Bash, all variables are globally scoped by default, so it is easy to accidentally clobber a variable:
444444

445-
```bash
445+
```{.bash .numberLines}
446446
#!/bin/bash
447447

448448
# 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`
467467

468468
### Tips
469469

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 `$`.
471471

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`.
473473
Rather than using `cd` and keeping track of where you were so you can `cd` back later, use `pushd` and `popd`.
474474
`pushd` pushes a new directory onto the directories stack and `popd` removes a directory from this stack.
475475
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
528528
Your `$PATH` may look something like this:
529529
```
530530
$ echo $PATH
531-
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
531+
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:
532+
/bin:/usr/games:/usr/local/games
532533
```
533534

534535
When you type in a command, say, `g++`, Bash looks through each directory in `$PATH` in order until it finds one with an executable named `g++` in it.
@@ -631,16 +632,12 @@ Boolean Logic:
631632

632633
### Statements
633634

634-
#### If
635-
636635
```bash
637636
if <condition>; then
638637
<commands to run>
639638
fi
640639
```
641640

642-
#### Case
643-
644641
```bash
645642
case <variable or expression> in
646643
first-case)
@@ -653,25 +650,23 @@ case <variable or expression> in
653650
esac
654651
```
655652

656-
#### Loops
657-
658-
Iterating loop:
653+
#### Iterating loop:
659654

660655
```bash
661656
for <variable-name> in <array>; do
662657
<commands>
663658
done
664659
```
665660

666-
Counting loop:
661+
#### Counting loop:
667662

668663
```bash
669664
for ((i=0; i < 7; i++)); do
670665
<commands>
671666
done
672667
```
673668

674-
While loop:
669+
#### While loop:
675670

676671
```bash
677672
while <condition>; do

0 commit comments

Comments
 (0)