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
  • Shell Script
  • Scripting
  • Automation
  • Programming
  • 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

VariableMeaning
$0Script 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

OperatorMeaningExample
-eqEqual[ $a -eq 5 ]
-neNot equal[ $a -ne 5 ]
-ltLess than[ $a -lt 10 ]
-leLess than or equal[ $a -le 10 ]
-gtGreater than[ $a -gt 0 ]
-geGreater than or equal[ $a -ge 0 ]

String Comparisons

OperatorMeaningExample
= or ==String equal[ "$str" = "hello" ]
!=String not equal[ "$str" != "world" ]
-zString is empty[ -z "$str" ]
-nString is not empty[ -n "$str" ]

File Tests

OperatorMeaning
-fFile exists
-dDirectory exists
-rFile is readable
-wFile is writable
-xFile is executable
-sFile 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 → filtering
  • NR, NF → built-in variables
  • sum += $2 → aggregation
  • arr[key]++ → grouping

🚀 Mental Model

AWK = Filter + Transform + Aggregate (all in one tool)

More bash concepts and examples will be added as needed!