scripting
Shell scripting techniques
-
jq
Tested jq examples: picking values out of nested JSON, filtering with select, reshaping objects, and getting raw strings back out into a shell script.
-
tee
Tested tee examples: saving a pipeline's output while still seeing it, appending with -a, and the sudo tee trick for writing files your shell cannot.
-
xargs
Tested xargs examples: batching with -n, placeholders with -I, NUL-separated input from find -print0, parallel runs with -P, and what its exit codes mean.
-
Environment variables and PATH
Why a program you can see and execute is still not found, how the environment is copied into each new process, and where PATH is really set on Debian.
-
Exit codes and error handling
How $?, PIPESTATUS, set -e, and pipefail combine to tell a script what succeeded and what failed, and where each one falls short.
-
Processes and signals
How processes are born, orphaned and reaped, what a signal actually does, why kill -9 is a last resort, and why Ctrl-C stops a whole pipeline at once.
-
Your first script
Write, mark executable, and run your first bash script, plus what the shebang line and PATH lookup do.
-
Variables and quoting
Why unquoted variables break bash scripts, when to use double vs single quotes, and how glob characters make it worse.
-
Conditionals and test
The difference between [ and [[ in bash, why unquoted variables crash [ but not [[, and pattern matching with case.
-
Loops
for, while and until in bash, iterating over files without breaking on spaces, and why a while read loop in a pipeline forgets everything it did.
-
Script arguments
How a script reads what it was called with: positional parameters, why "$@" and "$*" are not the same, shift, and parsing real flags with getopts.
-
Functions
Defining bash functions, why return gives a status not a value, how to hand data back, and why local separates a helper from a landmine.
-
Arrays
Indexed and associative arrays in bash: building them, why the @ and * subscripts differ, and filling one from command output without splitting.
-
Parameter expansion
Bash parameter expansion: default values with :-, trimming paths with # and %, replacing text with //, and slicing, length and case conversion.
-
Where a script lives
What $0 really contains, why a script cannot find a file next to itself with a relative path, and the BASH_SOURCE line that works through a symlink.
-
Arithmetic
Integer arithmetic in bash with $(( )) and (( )), -eq against =, why a leading zero is an error, and the awk one-liner for sums bash cannot do.
-
Here-docs and generating files
Here-documents in bash: feeding a block of text to a command, quoting the terminator to stop expansion, generating config files, and here-strings.
-
Traps and cleanup
The mktemp and trap EXIT pattern for scripts that clean up after themselves, why the trap body needs single quotes, and what set -e does not cover.
-
Debugging and robustness
Reading what a script actually did with bash -x and PS4, checking syntax without running it, making unset variables fatal, and what shellcheck catches.
-
A real script
A capstone backup script using arguments, arrays, parameter expansion, a trap and real exit codes, and how to schedule it with cron or a systemd timer.
-
Add a directory to your PATH permanently
How to put a directory on PATH for good on Debian, why ~/.local/bin needs no configuration at all, and what to do for any other directory.
-
Bulk rename a batch of files
Rename many files at once with a plain bash loop, safely handling spaces and previewing changes before committing.
-
sh vs bash vs dash
On Debian /bin/sh is dash, not bash. That one fact explains most scripts that work at your prompt and fail the moment something else runs them.
-
which vs type vs command -v
which searches PATH and nothing else, so it reports that cd does not exist. What type and command -v answer instead, and which one belongs in a script.