From c4ebf330366a3801e4081b6255e63c1e975b6cd8 Mon Sep 17 00:00:00 2001 From: Joshua Levy Date: Mon, 17 Aug 2015 00:20:16 -0700 Subject: [PATCH 1/2] Cover set -v, set -u, and more on trap. --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d7df0ca..bc5e9f8 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,11 @@ Notes: - Use `alias` to create shortcuts for commonly used commands. For example, `alias ll='ls -latr'` creates a new alias `ll`. -- In Bash scripts, use `set -x` for debugging output. Use strict modes whenever possible. Use `set -e` to abort on errors. Use `set -o pipefail` as well, to be strict about errors (though this topic is a bit subtle). For more involved scripts, also use `trap`. +- In Bash scripts, use `set -x` (or the variant `set -v`, which logs raw input, including unexpanded variables and comments) for debugging output. Use strict modes whenever possible: Use `set -e` to abort on errors and `set -o pipefail` as to abort within pipes, too (though this topic is a bit subtle). Use `set -u` to detect unset variable usages. For more involved scripts, also use `trap` on EXIT or ERR. A useful habit is to start a script like so, which will make it detect and abort on common errors and print a message: +```bash + set -euo pipefail + trap "echo 'error: Script failed: see last command above'" ERR +``` - In Bash scripts, subshells (written with parentheses) are convenient ways to group commands. A common example is to temporarily move to a different working directory, e.g. ```bash @@ -118,7 +122,7 @@ Notes: - In Bash, note there are lots of kinds of variable expansion. Checking a variable exists: `${name:?error message}`. For example, if a Bash script requires a single argument, just write `input_file=${1:?usage: $0 input_file}`. Arithmetic expansion: `i=$(( (i + 1) % 5 ))`. Sequences: `{1..10}`. Trimming of strings: `${var%suffix}` and `${var#prefix}`. For example if `var=foo.pdf`, then `echo ${var%.pdf}.txt` prints `foo.txt`. -- Brace expansion using `{`...`}` can reduce having to re-type similar text and automate combinations of items. This is helpful in examples like `mv foo.{txt,pdf} some-dir` (which moves both files), `cp somefile{,.bak}` (which expands to +- Brace expansion using `{`...`}` can reduce having to re-type similar text and automate combinations of items. This is helpful in examples like `mv foo.{txt,pdf} some-dir` (which moves both files), `cp somefile{,.bak}` (which expands to `cp somefile somefile.bak`) or `mkdir -p test-{a,b,c}/subtest-{1,2,3}` (which expands all possible combinations and creates a directory tree). - The output of a command can be treated like a file via `<(some command)`. For example, compare local `/etc/hosts` with a remote one: From eb7972cfa97f7ef54e5b7c557c0deb686482fea4 Mon Sep 17 00:00:00 2001 From: Joshua Levy Date: Mon, 17 Aug 2015 00:23:22 -0700 Subject: [PATCH 2/2] Improve last commit. --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bc5e9f8..2705c24 100644 --- a/README.md +++ b/README.md @@ -107,10 +107,10 @@ Notes: - Use `alias` to create shortcuts for commonly used commands. For example, `alias ll='ls -latr'` creates a new alias `ll`. -- In Bash scripts, use `set -x` (or the variant `set -v`, which logs raw input, including unexpanded variables and comments) for debugging output. Use strict modes whenever possible: Use `set -e` to abort on errors and `set -o pipefail` as to abort within pipes, too (though this topic is a bit subtle). Use `set -u` to detect unset variable usages. For more involved scripts, also use `trap` on EXIT or ERR. A useful habit is to start a script like so, which will make it detect and abort on common errors and print a message: +- In Bash scripts, use `set -x` (or the variant `set -v`, which logs raw input, including unexpanded variables and comments) for debugging output. Use strict modes unless you have a good reason not to: Use `set -e` to abort on errors (nonzero exit code). Use `set -u` to detect unset variable usages. Consider `set -o pipefail` too, to on errors within pipes, too (though read up on it more if you do, as this topic is a bit subtle). For more involved scripts, also use `trap` on EXIT or ERR. A useful habit is to start a script like this, which will make it detect and abort on common errors and print a message: ```bash set -euo pipefail - trap "echo 'error: Script failed: see last command above'" ERR + trap "echo 'error: Script failed: see failed command above'" ERR ``` - In Bash scripts, subshells (written with parentheses) are convenient ways to group commands. A common example is to temporarily move to a different working directory, e.g. @@ -122,8 +122,7 @@ Notes: - In Bash, note there are lots of kinds of variable expansion. Checking a variable exists: `${name:?error message}`. For example, if a Bash script requires a single argument, just write `input_file=${1:?usage: $0 input_file}`. Arithmetic expansion: `i=$(( (i + 1) % 5 ))`. Sequences: `{1..10}`. Trimming of strings: `${var%suffix}` and `${var#prefix}`. For example if `var=foo.pdf`, then `echo ${var%.pdf}.txt` prints `foo.txt`. -- Brace expansion using `{`...`}` can reduce having to re-type similar text and automate combinations of items. This is helpful in examples like `mv foo.{txt,pdf} some-dir` (which moves both files), `cp somefile{,.bak}` (which expands to -`cp somefile somefile.bak`) or `mkdir -p test-{a,b,c}/subtest-{1,2,3}` (which expands all possible combinations and creates a directory tree). +- Brace expansion using `{`...`}` can reduce having to re-type similar text and automate combinations of items. This is helpful in examples like `mv foo.{txt,pdf} some-dir` (which moves both files), `cp somefile{,.bak}` (which expands to `cp somefile somefile.bak`) or `mkdir -p test-{a,b,c}/subtest-{1,2,3}` (which expands all possible combinations and creates a directory tree). - The output of a command can be treated like a file via `<(some command)`. For example, compare local `/etc/hosts` with a remote one: ```sh