LinuxCommandLibrary
GitHub F-Droid Google Play Store

Shell Scripting

Script Basics

A shell script is a text file containing commands that the shell executes in sequence. The first line should be a shebang that tells the system which interpreter to use.
$ #!/bin/bash
copy
$ #!/usr/bin/env bash
copy
Make the script executable and run it.
$ chmod +x script.sh
copy
$ ./script.sh
copy
Use set options at the top of scripts to catch errors early: -e exits on the first error, -u treats unset variables as errors, -o pipefail makes a pipeline fail if any command in it fails.
$ set -euo pipefail
copy

Variables

Variable assignment has no spaces around the = sign. Use double quotes around variable references to prevent word splitting.
ExpressionDescription
VAR=valueAssign a value
VAR=$(command)Capture command output (command substitution)
$VARRead the value
${VAR}Read with explicit boundary
"$VAR"Read safely with quoting
${VAR:-default}Use default if VAR is unset or empty
${VAR:=default}Assign default if VAR is unset or empty
${VAR:+alternate}Use alternate if VAR is set and not empty
${VAR:?error msg}Exit with error if VAR is unset or empty
${#VAR}Length of the value
readonly VARMake variable read-only
export VARMake variable available to child processes

Quoting

Quoting controls what the shell expands. When in doubt, use double quotes.
ExpressionDescription
'text'Single quotes: everything is literal
"text"Double quotes: $variables and $(commands) are expanded
\$HOMEBackslash escapes a single character
Always quote variable references: "$VAR" survives spaces in the value, unquoted $VAR gets split into separate words.

Special Variables

These are set automatically by the shell inside a running script.
VariableDescription
0ドルName of the script
1ドル..9ドルPositional parameters (arguments)
${10}Positional parameters beyond 9
$#Number of arguments
$@All arguments as separate words
$*All arguments as a single string
$?Exit status of the last command
$$PID of the current shell
$!PID of the last background command
$_Last argument of the previous command
Prefer "$@" when passing arguments on to another command: it preserves each argument as a separate word.

String Operations

Bash provides built-in string manipulation without needing external commands.
ExpressionDescription
${VAR#pattern}Remove shortest match from start
${VAR##pattern}Remove longest match from start
${VAR%pattern}Remove shortest match from end
${VAR%%pattern}Remove longest match from end
${VAR/old/new}Replace first occurrence
${VAR//old/new}Replace all occurrences
${VAR:offset}Substring from offset
${VAR:offset:length}Substring from offset with length
${VAR^}Uppercase first character
${VAR^^}Uppercase all characters
${VAR,}Lowercase first character
${VAR,,}Lowercase all characters
Case conversion (${VAR^^}, ${VAR,,}) requires bash 4 or later.

Conditionals

Use [[ ]] for conditionals in bash scripts. It supports pattern and regex matching and is safer than the older [ ] form. The spaces inside the brackets are required.
$ if [[ -f "file.txt" ]]; then echo "exists"; fi
copy
OperatorDescription
-f fileTrue if file exists and is a regular file
-d fileTrue if file exists and is a directory
-e fileTrue if file exists (any type)
-r fileTrue if file is readable
-w fileTrue if file is writable
-x fileTrue if file is executable
-s fileTrue if file exists and is not empty
-z stringTrue if string is empty
-n stringTrue if string is not empty
==String equality (right side is a glob pattern)
!=String inequality
=~Regex match (inside [[ ]])
-eqNumeric equality
-neNumeric inequality
-ltNumeric less than
-leNumeric less than or equal
-gtNumeric greater than
-geNumeric greater than or equal
$ if [[ "$count" -gt 0 ]]; then echo "positive"; elif [[ "$count" -eq 0 ]]; then echo "zero"; else echo "negative"; fi
copy
$ if [[ "$input" =~ ^[0-9]+$ ]]; then echo "is a number"; fi
copy
The case statement matches a value against glob patterns.
$ case "1ドル" in start) echo "Starting";; stop) echo "Stopping";; *) echo "Usage: 0ドル {start|stop}";; esac
copy

Loops

The for loop iterates over a list of items.
$ for file in *.txt; do echo "$file"; done
copy
$ for i in {1..10}; do echo "$i"; done
copy
$ for ((i=0; i<10; i++)); do echo "$i"; done
copy
The while loop runs as long as the condition is true. This is the safe way to read a file line by line.
$ while IFS= read -r line; do echo "$line"; done < file.txt
copy
The until loop runs until the condition becomes true.
$ until [[ -f "ready.flag" ]]; do sleep 1; done
copy
Use break to exit a loop early and continue to skip to the next iteration.

Functions

Functions group reusable commands. Arguments are accessed with 1ドル, 2ドル, etc. inside the function body. Use local to keep variables scoped to the function.
$ greet() { local name="1ドル"; echo "Hello, $name"; }
copy
$ greet "World"
copy
A function returns its last command's exit status, or use return to set an explicit exit code (0-255). To return strings, use command substitution.
$ get_date() { date +%Y-%m-%d; }
copy
$ today=$(get_date)
copy

Arrays

Bash supports indexed arrays. Declare and manipulate them as follows.
ExpressionDescription
arr=(a b c)Declare an array
arr[0]=valueSet element by index
${arr[0]}Access element by index
"${arr[@]}"All elements, one word each
${#arr[@]}Number of elements
${arr[@]:1:2}Slice: 2 elements starting at index 1
arr+=(d e)Append elements
${!arr[@]}All indices
unset 'arr[1]'Remove an element (indices keep a gap)
Loop over all elements with the array quoted, so elements with spaces stay intact.
$ for item in "${arr[@]}"; do echo "$item"; done
copy
Associative arrays (string keys) require explicit declaration.
$ declare -A map
copy
$ map[key]="value"
copy
$ echo "${map[key]}"
copy

Arithmetic

Use $(( )) for arithmetic expressions and (( )) for arithmetic statements.
ExpressionDescription
$((a + b))Addition
$((a - b))Subtraction
$((a * b))Multiplication
$((a / b))Integer division
$((a % b))Modulo
$((a ** b))Exponentiation
$((a++))Post-increment
$((++a))Pre-increment
((a += 5))Arithmetic assignment
Shell arithmetic is integer only. Pipe to bc for floating point math.
$ echo "scale=2; 10 / 3" | bc
copy

Input and Output

Use read to get input from the user or from a file.
$ read -p "Enter name: " name
copy
$ read -s -p "Password: " pass
copy
$ read -r -a items <<< "a b c"
copy
Use printf for formatted output, it is more portable and predictable than echo.
$ printf "Name: %s, Age: %d\n" "$name" "$age"
copy
A here document passes multi-line text to a command's standard input.
$ cat <<EOF
Hello, $USER
Your home is $HOME
EOF
copy
Use <<'EOF' (quoted) to prevent variable expansion inside the here document.

Exit Codes and Traps

Every command returns an exit code: 0 means success, anything else means failure. The code of the last command is in $?. Use exit to set the script's own exit code.
$ command || exit 1
copy
$ command && echo "succeeded"
copy
Use trap to run cleanup code when the script exits or receives a signal. The EXIT trap runs on any exit, including errors.
$ tmpfile=$(mktemp)
copy
$ trap 'rm -f "$tmpfile"' EXIT
copy
$ trap 'echo "Interrupted"; exit 130' INT TERM
copy

Debugging

Check the syntax without executing the script.
$ bash -n script.sh
copy
Trace every command as it runs, with variables expanded.
$ bash -x script.sh
copy
Turn tracing on and off inside a script.
$ set -x
copy
$ set +x
copy
Lint scripts for common mistakes and pitfalls.
$ shellcheck script.sh
copy
Copied to clipboard
Kai

AltStyle によって変換されたページ (->オリジナル) /