Bash Scripting & Language Guide
Comprehensive guide to Bash scripting, shell commands, variables, functions, conditional logic, loops, and advanced scripting concepts for automation and system administration.
Bash (Bourne Again Shell) is the most widely used shell scripting language in Linux and macOS. This guide covers bash language fundamentals, scripting patterns, and practical examples for automation and system administration.
Prerequisites & Setup
#!/bin/bash
This "shebang" line tells the system to execute the script using bash
Always place it at the very first line of your script
chmod +x script.sh
Make the script executable
./script.sh
Run the script
Variables & Data Types
Variable Declaration & Usage
name="Adarsh"
Declare a string variable (no spaces around =)
age=25
Declare a numeric variable
echo $name
Access variable with $ prefix
echo ${name}
Alternative syntax with curly braces (preferred in complex cases)
echo "$name is $age years old"
Variables expand inside double quotes
echo '$name is $age years old'
Variables do NOT expand inside single quotes (literal string)
read NAME
echo "Welcome $NAME"
Accept value from user
Variable Scope
local var="value"
Declare local variable (only in functions)
export VAR="value"
Make variable available to child processes/scripts
unset var
Delete/unset a variable
readonly PI=3.14159
Declare immutable variable
Special Variables
| Variable | Meaning |
|---|---|
$0 | Script name |
$1, $2, $3... | Positional arguments (1st, 2nd, 3rd…) |
$@ | All arguments as separate words |
$* | All arguments as single string |
$# | Number of arguments |
$? | Exit status of last command (0=success, non-zero=error) |
$$ | Process ID (PID) of current script |
$! | PID of last background process |
$- | Flags passed to shell |
Arithmetic Operations
Basic Arithmetic
sum=$((5 + 3))
Addition (result: 8)
diff=$((10 - 4))
Subtraction (result: 6)
product=$((4 * 7))
Multiplication (result: 28)
quotient=$((20 / 4))
Integer division (result: 5)
remainder=$((17 % 5))
Modulo/remainder operator (result: 2)
power=$((2 ** 3))
Exponentiation (result: 8)
Increment & Decrement
x=5
((x++))
Post-increment (x becomes 6)
y=5
((++y))
Pre-increment (y becomes 6, difference matters in expressions)
z=10
((z--))
Post-decrement (z becomes 9)
w=10
((--w))
Pre-decrement (w becomes 9)
a=5
a=$((a + 3))
Add to variable (result: 8)
b=20
b=$((b - 5))
Subtract from variable (result: 15)
c=4
((c *= 3))
Multiply assign (c becomes 12)
d=100
((d /= 5))
Divide assign (d becomes 20)
Arithmetic Comparison
if (( a > b )); then
echo "a is greater than b"
fi
if (( x == 5 )); then
echo "x equals 5"
fi
if (( y != 0 )); then
echo "y is not zero"
fi
if (( z <= 10 )); then
echo "z is less than or equal to 10"
fi
Operators in (( )):
(( a > b )) greater than
(( a < b )) less than
(( a >= b )) greater than or equal
(( a <= b )) less than or equal
(( a == b )) equal
(( a != b )) not equal
Complex Arithmetic Expressions
result=$((5 + 3 * 2))
Follows order of operations (result: 11, not 16)
result=$(((5 + 3) * 2))
Use parentheses for grouping (result: 16)
counter=0
result=$((++counter + counter + ++counter))
Complex expression with increments (result: 3)
bitwise_and=$((5 & 3))
Bitwise AND (result: 1)
bitwise_or=$((5 | 3))
Bitwise OR (result: 7)
bitwise_xor=$((5 ^ 3))
Bitwise XOR (result: 6)
bitwise_not=$((~5))
Bitwise NOT (result: -6)
left_shift=$((5 << 2))
Left shift (result: 20)
right_shift=$((20 >> 2))
Right shift (result: 5)
ternary=$((x > 5 ? 10 : 20))
Ternary operator (if x > 5 then 10 else 20)
Float/Decimal Arithmetic
Only integers are supported in (( ))
For floating-point, use bc or awk
result=$(echo "5.5 + 2.3" | bc)
Using bc calculator
result=$(awk "BEGIN {print 5.5 + 2.3}")
Using awk for floating-point
result=$(python3 -c "print(5.5 + 2.3)")
Using Python for precise floating-point
Examples
Increment counter in loop:
counter=0
for i in {1..5}; do
((counter++))
done
echo $counter # Output: 5
Calculate average:
sum=$((5 + 10 + 15))
avg=$((sum / 3))
echo $avg # Output: 10
Conditional arithmetic:
age=25
if (( age >= 18 && age <= 65 )); then
echo "Working age"
fi
Array index calculation:
arr=(a b c d e)
index=$((2 + 1))
echo ${arr[$index]} # Output: d (index 3)
String Operations
str="Hello World"
length=${#str}
Get string length (9 characters, spaces count)
substring=${str:0:5}
Extract substring from position 0, length 5 ("Hello")
substring=${str:6}
Extract from position 6 to end ("World")
newstr=${str/World/Universe}
Replace first occurrence
newstr=${str//o/0}
Replace all occurrences (World -> W0rld 0)
if [[ $str == *"World"* ]]; then
Check if string contains substring
str_upper=${str^^}
Convert to uppercase (bash 4+)
str_lower=${str,,}
Convert to lowercase (bash 4+)
trimmed=${str// /}
Remove all spaces
IFS=',' read -ra arr <<< $str
Split string by delimiter into array
Arrays
Array Declaration & Access
arr=(one two three four)
Declare indexed array
arr[0]="first"
Set specific index
echo ${arr[0]}
Access single element
echo ${arr[@]}
Print all elements
echo ${#arr[@]}
Get array length
unset arr[1]
Delete element at index 1
Array Iteration
for item in "${arr[@]}"; do
echo $item
done
for i in "${!arr[@]}"; do
echo "Index $i: ${arr[$i]}"
done
Associative Arrays (Dictionaries)
declare -A dict
Declare associative array
dict[name]="Adarsh"
Set key-value pair
dict[age]=25
echo ${dict[name]}
Access value by key
echo ${!dict[@]}
Print all keys
echo ${dict[@]}
Print all values
Conditional Logic
if/else Statements
if [ $age -gt 18 ]; then
echo "Adult"
elif [ $age -eq 18 ]; then
echo "Just turned 18"
else
echo "Minor"
fi
Comparison Operators
Numeric Comparisons
| Operator | Meaning | Example |
|---|---|---|
-eq | Equal | [ $a -eq 5 ] |
-ne | Not equal | [ $a -ne 5 ] |
-lt | Less than | [ $a -lt 10 ] |
-le | Less than or equal | [ $a -le 10 ] |
-gt | Greater than | [ $a -gt 0 ] |
-ge | Greater than or equal | [ $a -ge 0 ] |
String Comparisons
| Operator | Meaning | Example |
|---|---|---|
= or == | String equal | [ "$str" = "hello" ] |
!= | String not equal | [ "$str" != "world" ] |
-z | String is empty | [ -z "$str" ] |
-n | String is not empty | [ -n "$str" ] |
File Tests
| Operator | Meaning |
|---|---|
-f | File exists |
-d | Directory exists |
-r | File is readable |
-w | File is writable |
-x | File is executable |
-s | File is non-empty |
Logical Operators
if [ $age -gt 18 ] && [ $age -lt 65 ]; then
echo "Working age"
fi
if [ $role = "admin" ] || [ $role = "superuser" ]; then
echo "Has elevated privileges"
fi
if ! [ -f $file ]; then
echo "File does not exist"
fi
Test Command Alternatives
[ condition ]
Traditional test syntax
[[ condition ]]
Modern bash test (supports regex, better word splitting)
if [[ $str == *"pattern"* ]]; then
Supports pattern matching
if [[ $num -gt 10 && $num -lt 20 ]]; then
&& works directly in [[ ]] (vs -a in [ ])
(( condition ))
Arithmetic evaluation
Loops
For Loop
for i in 1 2 3 4 5; do
echo $i
done
for i in {1..10}; do
echo $i
done
Range expansion (1 to 10)
for i in {1..10..2}; do
echo $i
done
Range with step (1, 3, 5, 7, 9)
for ((i=1; i<=10; i++)); do
echo $i
done
C-style for loop
for file in *.txt; do
echo "Processing $file"
done
Loop through files
While Loop
counter=1
while [ $counter -le 5 ]; do
echo $counter
((counter++))
done
while IFS= read -r line; do
echo "Line: $line"
done < file.txt
Read file line by line
while true; do
echo "Infinite loop (break to exit)"
break
done
Until Loop
count=1
until [ $count -gt 5 ]; do
echo $count
((count++))
done
Loop until condition is true
Loop Control
break
Exit loop immediately
continue
Skip to next iteration
for i in {1..10}; do
if [ $i -eq 5 ]; then
continue
fi
echo $i
done
Skip number 5
Functions
Function Definition & Calling
function greet() {
echo "Hello $1"
}
greet "Adarsh"
Call function with argument
greet
Also valid syntax without the 'function' keyword
Alternative syntax:
greet() {
echo "Hello $1"
}
Function Parameters & Return Values
function add() {
local sum=$(($1 + $2))
echo $sum
}
result=$(add 5 3)
echo $result
Output: 8
Capture function output
function check_file() {
if [ -f "$1" ]; then
return 0
else
return 1
fi
}
if check_file "script.sh"; then
echo "File exists"
fi
Local Variables in Functions
function outer() {
local x=10
inner
}
function inner() {
echo $x
}
x is local to outer, inner cannot access
Command Substitution & Expansion
result=$(ls -la)
Capture command output (modern syntax)
result=`ls -la`
Capture command output (legacy backtick syntax)
echo "Files: $(ls | wc -l)"
Nested command substitution
sum=$((5 + 3))
Arithmetic expansion
name=${name:="default"}
Parameter expansion with default value
echo The time is $(date +%H:%M:%S)
Get current time
Input/Output
Reading Input
read name
Wait for user input and store in name
read -p "Enter name: " name
Prompt before reading
read -s password
Read without echoing (for passwords)
read -n 1 char
Read single character
read -t 5 input
Read with timeout (5 seconds)
read -a array <<< "one two three"
Read into array
Output
echo "Hello World"
Print with newline
echo -n "No newline"
Print without newline
echo -e "Line 1\nLine 2"
Enable interpretation of backslash escapes
printf "%s %d\n" "Age:" 25
Formatted output (like C printf)
>&2 echo "Error message"
Print to stderr instead of stdout
String Templates & Here Documents
cat << EOF
Multi-line string
Can contain variables: $name
Preserves formatting
EOF
cat << 'EOF'
Single quotes prevent variable expansion
$name will NOT be replaced
Useful for literal text
EOF
cat << -EOF
Same as above but allows indentation
(-EOF means tabs are stripped)
EOF
Error Handling
Exit Codes
command
Do something
if [ $? -eq 0 ]; then
echo "Success"
else
echo "Failed with code $?"
fi
command || echo "Failed"
Execute command, echo if fails
command && echo "Success"
Execute command, echo if succeeds
command && echo "Success" || echo "Failed"
Ternary-like syntax
Set Options
set -e
Exit script if any command fails (recommended)
set -u
Exit if undefined variable is used
set -o pipefail
Fail if any command in pipeline fails
set -x
Debug mode (print each command before executing)
Trap Cleanup
trap "cleanup" EXIT
Run cleanup function when script exits
trap "echo 'Script interrupted'; exit" INT
Handle Ctrl+C interrupt
function cleanup() {
rm -f temp_file.txt
echo "Cleaned up!"
}
trap cleanup EXIT
Debugging
bash -x script.sh
Run script in debug mode (prints commands)
set -x
Enable debug mode inside script
set +x
Disable debug mode
echo "Debug: var=$var"
Add debug print statements
PS4='+ $(date "+%s") ${BASH_SOURCE}:${LINENO}: '
Customize debug output format
🧾 AWK Cheat Sheet (Practical Commands + One-Line Notes)
🟢 Basic Printing
awk '{print}' file.txt
Print entire file (like cat)
awk '{print $0}' file.txt
Print full line explicitly
awk '{print $1}' file.txt
Print first column
awk '{print $1, $2}' file.txt
Print multiple columns (auto space separated)
🟢 Filtering
awk '$2 > 25 {print $1}' file.txt
Print column 1 where column 2 > 25
awk '$4 >= 400 {print $1}' access.log
Filter rows based on condition (like WHERE in SQL)
awk '/error/ {print}' file.txt
Print lines matching pattern (like grep)
🟢 Field Separator
awk -F ',' '{print $1}' file.csv
Use comma as delimiter instead of space
awk -F '\t' '{print $1}' file.txt
Use tab as delimiter
🟢 Built-in Variables
awk '{print NR, $0}' file.txt
Print line number with line
awk '{print NF}' file.txt
Print number of fields in each line
🟢 String Formatting
awk '{print $1 " is adult"}' file.txt
Concatenate strings manually
awk '{print $1, "is adult"}' file.txt
Comma adds automatic spacing
awk '{printf "Line %d: %s (%d)\n", NR, $1, $2}'
Formatted output (precise control like C)
🟢 Calculations
awk '{sum += $2} END {print sum}' file.txt
Sum values of column 2
awk '{sum += $2} END {print sum/NR}' file.txt
Calculate average
awk '{sum += $2} {print sum}' file.txt
Print running sum (line by line accumulation)
🟢 BEGIN / END Blocks
awk 'BEGIN {print "Start"} {print $1} END {print "Done"}' file.txt
Run setup before and summary after processing
🟢 Conditionals
awk '{if ($2 > 50) print $1, "PASS"; else print $1, "FAIL"}'
Use if-else logic inside AWK
🟢 Arrays (🔥 most important)
awk '{count[$2]++} END {for (m in count) print m, count[m]}'
Count occurrences (group by key)
awk '{sum[$3] += $5} END {for (k in sum) print k, sum[k]}'
Aggregate values per key (group + sum)
🟢 Real Log Use Cases
awk '$4 == 200 {count++} END {print count}' access.log
Count successful requests
awk '$4 == 200 {sum += $5} END {print sum}' access.log
Total bytes for successful requests
awk '{count[$1]++} END {for (ip in count) print ip, count[ip]}' access.log
Count requests per IP
🟢 Sorting Output
awk '{count[$2]++} END {for (m in count) print m, count[m]}' file.txt | sort
Sort final output
🧠 Ultimate Pattern (Most Important)
awk '{bucket[key] += value} END {for (k in bucket) print k, bucket[k]}'
Group by key and aggregate values (like SQL GROUP BY)
⚡ 80/20 Rules
$1, $2→ columns$2 > 25→ filteringNR,NF→ built-in variablessum += $2→ aggregationarr[key]++→ grouping
🚀 Mental Model
AWK = Filter + Transform + Aggregate (all in one tool)
More bash concepts and examples will be added as needed!