Bash Scripting Cheatsheet
Comprehensive reference guide for Bash shell scripting. Search, browse, and learn essential Bash commands, syntax, and best practices for writing robust shell scripts.
240 commands
Getting Started
Script Header
#!/usr/bin/env bash | Recommended shebang for portability |
#!/bin/bash | Direct path shebang |
set -euo pipefail | Strict mode: exit on error, unset vars, pipe failures |
IFS=$'\n\t' | Set Internal Field Separator to newline and tab |
💡 Always use strict mode for safer scripts
Getting Started
Variables
name="John" | Define variable (no spaces around =) |
echo $name | Use variable |
echo "$name" | Use variable (recommended) |
echo "${name}!" | Use variable with braces |
readonly name="John" | Define constant variable |
local name="John" | Local variable (inside function) |
unset name | Unset/delete variable |
Getting Started
String Quotes
echo "Hi $name" | Double quotes: variables expanded |
echo 'Hi $name' | Single quotes: literal string |
echo "I'm in $(pwd)" | Command substitution in string |
Getting Started
Shell Execution
$(command) | Command substitution (preferred) |
`command` | Command substitution (legacy) |
eval "$cmd" | Execute string as command |
Getting Started
Conditional Execution
cmd1 && cmd2 | Run cmd2 if cmd1 succeeds |
cmd1 || cmd2 | Run cmd2 if cmd1 fails |
cmd1 ; cmd2 | Run both commands sequentially |
cmd & | Run command in background |
Variables
Parameter Expansion Basics
${name} | Variable value |
${name/J/j} | Substitution: John → john |
${name:0:2} | Substring: position 0, length 2 |
${name::2} | Substring: first 2 chars |
${name::-1} | Substring: remove last char |
${name:(-1)} | Substring: last char only |
${#name} | Length of variable |
Variables
Default Values
${foo:-val} | $foo, or val if unset/null |
${foo:=val} | Set $foo to val if unset/null |
${foo:+val} | val if $foo is set (not null) |
${foo:?message} | Error and exit if $foo unset/null |
💡 Omit : to only check if unset (not null)
Variables
String Manipulation
${str%suffix} | Remove shortest suffix match |
${str%%suffix} | Remove longest suffix match |
${str#prefix} | Remove shortest prefix match |
${str##prefix} | Remove longest prefix match |
${str/from/to} | Replace first match |
${str//from/to} | Replace all matches |
${str/#from/to} | Replace prefix |
${str/%from/to} | Replace suffix |
Variables
Case Manipulation
${str,} | Lowercase first character |
${str,,} | Lowercase all characters |
${str^} | Uppercase first character |
${str^^} | Uppercase all characters |
Variables
Path Manipulation
${path%.cpp} | Remove extension: /path/to/foo |
${path##*/} | Get basename: foo.cpp |
${path%/*} | Get directory: /path/to |
${path##*.} | Get extension: cpp |
Conditionals
If Statement
if [[ condition ]]; then | Start if block |
elif [[ condition ]]; then | Else if |
else | Else block |
fi | End if block |
Conditionals
String Conditions
[[ -z "$str" ]] | String is empty |
[[ -n "$str" ]] | String is not empty |
[[ "$a" == "$b" ]] | Strings are equal |
[[ "$a" != "$b" ]] | Strings are not equal |
[[ "$a" < "$b" ]] | String a is less than b (alphabetically) |
[[ "$a" =~ regex ]] | String matches regex |
Conditionals
Numeric Conditions
[[ $a -eq $b ]] | Equal |
[[ $a -ne $b ]] | Not equal |
[[ $a -lt $b ]] | Less than |
[[ $a -le $b ]] | Less than or equal |
[[ $a -gt $b ]] | Greater than |
[[ $a -ge $b ]] | Greater than or equal |
(( a < b )) | Arithmetic comparison |
Conditionals
File Conditions
[[ -e file ]] | File exists |
[[ -f file ]] | Is a regular file |
[[ -d file ]] | Is a directory |
[[ -r file ]] | File is readable |
[[ -w file ]] | File is writable |
[[ -x file ]] | File is executable |
[[ -s file ]] | File size > 0 bytes |
[[ -h file ]] | Is a symlink |
[[ f1 -nt f2 ]] | f1 is newer than f2 |
[[ f1 -ot f2 ]] | f1 is older than f2 |
Conditionals
Logical Operators
[[ ! expr ]] | Not |
[[ expr1 && expr2 ]] | And |
[[ expr1 || expr2 ]] | Or |
Conditionals
Case Statement
case "$var" in | Start case statement |
pattern1) commands ;; | Pattern with commands |
pattern1|pattern2) cmd ;; | Multiple patterns |
*) default ;; | Default case |
esac | End case statement |
Loops
For Loop
for i in /etc/rc.*; do | Loop over files |
for i in {1..5}; do | Loop over range |
for i in {5..50..5}; do | Range with step |
for ((i=0; i<10; i++)); do | C-style for loop |
for i in "${arr[@]}"; do | Loop over array |
done | End loop |
Loops
While Loop
while [[ condition ]]; do | While loop |
while true; do | Infinite loop |
while read -r line; do | Read file line by line |
done < file.txt | Read from file |
done < <(command) | Read from command output |
Loops
Until Loop
until [[ condition ]]; do | Loop until condition is true |
done | End loop |
Loops
Loop Control
break | Exit loop |
break 2 | Exit 2 levels of loops |
continue | Skip to next iteration |
continue 2 | Continue outer loop |
Functions
Defining Functions
myfunc() { ... } | Define function (preferred) |
function myfunc { ... } | Define function (alternate) |
myfunc "arg1" "arg2" | Call function with arguments |
Functions
Function Arguments
$# | Number of arguments |
$* | All arguments as single string |
$@ | All arguments as separate strings |
$1, $2, ... | Individual arguments |
$0 | Script name |
${@:2} | All arguments from 2nd |
${@:2:3} | 3 arguments starting from 2nd |
💡 Always quote $@ as "$@" to preserve arguments
Functions
Return Values
return 0 | Return success (0) |
return 1 | Return failure (non-zero) |
result=$(myfunc) | Capture function output |
local var="value" | Local variable in function |
Arrays
Indexed Arrays
arr=("a" "b" "c") | Define array |
arr[0]="value" | Set element |
${arr[0]} | Get element |
${arr[-1]} | Get last element |
${arr[@]} | All elements |
${#arr[@]} | Array length |
${!arr[@]} | All indices |
${arr[@]:1:2} | Slice: from index 1, length 2 |
Arrays
Array Operations
arr+=("item") | Append element |
unset arr[2] | Remove element at index |
arr=("${arr[@]}") | Rebuild array (remove gaps) |
arr=("${arr[@]}" "${arr2[@]}") | Concatenate arrays |
Arrays
Associative Arrays (Dictionaries)
declare -A dict | Declare associative array |
dict[key]="value" | Set key-value |
${dict[key]} | Get value by key |
${!dict[@]} | All keys |
${dict[@]} | All values |
${#dict[@]} | Number of elements |
unset dict[key] | Delete key |
Arrays
Array Iteration
for val in "${arr[@]}"; do | Iterate over values |
for key in "${!dict[@]}"; do | Iterate over keys |
for i in "${!arr[@]}"; do | Iterate with index |
I/O & Redirection
Output Redirection
cmd > file | Redirect stdout to file (overwrite) |
cmd >> file | Redirect stdout to file (append) |
cmd 2> file | Redirect stderr to file |
cmd 2>&1 | Redirect stderr to stdout |
cmd &> file | Redirect both stdout and stderr |
cmd &>> file | Append both stdout and stderr |
cmd >/dev/null 2>&1 | Discard all output |
I/O & Redirection
Input Redirection
cmd < file | Read stdin from file |
cmd <<< "string" | Here string |
cmd << EOF\n...\nEOF | Here document |
I/O & Redirection
Pipes
cmd1 | cmd2 | Pipe stdout to next command |
cmd1 |& cmd2 | Pipe stdout and stderr |
cmd | tee file | Pipe and save to file |
cmd | xargs cmd2 | Pass output as arguments |
I/O & Redirection
Process Substitution
diff <(cmd1) <(cmd2) | Compare outputs of two commands |
cmd > >(process) | Send output to process |
while read line; do ... done < <(cmd) | Read command output in loop |
I/O & Redirection
Reading Input
read var | Read line into variable |
read -r var | Read without backslash escaping |
read -p "Prompt: " var | Read with prompt |
read -s var | Read silently (for passwords) |
read -n 1 var | Read single character |
read -t 5 var | Read with 5 second timeout |
read -a arr | Read into array |
Options & Settings
Set Options
set -e | Exit on error (errexit) |
set -u | Error on unset variables (nounset) |
set -o pipefail | Fail on pipe errors |
set -x | Print commands before execution (debug) |
set -n | Check syntax without executing |
set -v | Print shell input lines |
set +e | Disable errexit (+ disables) |
Options & Settings
Shopt Options
shopt -s nullglob | Non-matching globs expand to nothing |
shopt -s failglob | Non-matching globs cause error |
shopt -s nocaseglob | Case-insensitive globbing |
shopt -s dotglob | Include hidden files in globs |
shopt -s globstar | Enable ** recursive glob |
shopt -s extglob | Extended pattern matching |
Options & Settings
Getting Options
while getopts "ab:c" opt; do | Parse short options |
case $opt in a) ... ;; esac | Handle each option |
$OPTARG | Option argument value |
$OPTIND | Index of next argument |
History & Expansion
History Commands
history | Show command history |
history -c | Clear history |
!! | Repeat last command |
!n | Execute command number n |
!-n | Execute nth previous command |
!string | Execute last command starting with string |
!?string | Execute last command containing string |
History & Expansion
History Expansion
!$ | Last argument of previous command |
!* | All arguments of previous command |
!^ | First argument of previous command |
!!:n | nth word of previous command |
!!:s/old/new/ | Substitute in previous command |
^old^new | Quick substitution |
History & Expansion
Brace Expansion
{a,b,c} | Expands to: a b c |
{1..5} | Expands to: 1 2 3 4 5 |
{a..z} | Expands to: a b c ... z |
{1..10..2} | Expands to: 1 3 5 7 9 |
file{1,2,3}.txt | Expands to: file1.txt file2.txt file3.txt |
{A,B}{1,2} | Expands to: A1 A2 B1 B2 |
History & Expansion
Arithmetic Expansion
$((a + b)) | Arithmetic expression |
$((a++)) | Increment |
$((a--)) | Decrement |
$((RANDOM % 100)) | Random number 0-99 |
declare -i num | Declare integer variable |
let "num = 5 + 3" | Arithmetic assignment |
Advanced
Special Variables
$? | Exit status of last command |
$$ | PID of current shell |
$! | PID of last background process |
$0 | Name of script |
$_ | Last argument of previous command |
${PIPESTATUS[@]} | Exit statuses of pipe commands |
$LINENO | Current line number |
$FUNCNAME | Current function name |
$BASH_SOURCE | Script filename |
Advanced
Traps & Signals
trap 'cmd' EXIT | Run cmd on script exit |
trap 'cmd' ERR | Run cmd on error |
trap 'cmd' INT | Run cmd on Ctrl+C |
trap 'cmd' TERM | Run cmd on termination |
trap - EXIT | Remove trap |
kill -SIGTERM $pid | Send signal to process |
Advanced
Subshells & Groups
(cmd1; cmd2) | Run in subshell |
{ cmd1; cmd2; } | Run in current shell (group) |
$(cmd) | Command substitution |
coproc cmd | Run as coprocess |
💡 Subshells don't affect parent environment
Advanced
Printf Formatting
printf "%s" "$var" | Print string |
printf "%d" 42 | Print integer |
printf "%f" 3.14 | Print float |
printf "%x" 255 | Print hex (ff) |
printf "%05d" 42 | Zero-padded (00042) |
printf "%-10s" "hi" | Left-aligned, width 10 |
Advanced
Debugging
bash -x script.sh | Run with debug output |
bash -n script.sh | Check syntax only |
set -x | Enable debug mode |
set +x | Disable debug mode |
echo "Debug: $var" >&2 | Print to stderr |
type command | Show command type/location |
command -v cmd | Check if command exists |
Advanced
String Operations
tr 'a-z' 'A-Z' | Translate characters |
tr -d '\n' | Delete characters |
tr -s ' ' | Squeeze repeated chars |
cut -d':' -f1 | Cut field by delimiter |
awk '{print $1}' | Print first field |
sed 's/old/new/g' | Replace text |
Quick Reference
Strict mode:
set -euo pipefail
Shebang:
#!/usr/bin/env bash
Debug:
bash -x script.sh
Check syntax:
bash -n script.sh