DEV Community

Maksym
Maksym

Posted on

Mastering Bash: A Complete Guide

Lately, I’ve started working on new projects that involve a lot of sysadmin responsibilities, so I need to level up my Bash skills to make my life a little easier.
Aliases already help me a lot — I’ve just figured out a system in my head, a kind of naming convention, for how I should call some daily commands that I might run hundreds of times per day.
So join me on this journey! We’ll cover not just simple aliases, but the real power of Bash scripts — a tool that can make your workflow faster, smarter, and way more fun. Enjoy! 😎

Bash (Bourne Again Shell) is the default shell for most Linux distributions and macOS systems. Mastering Bash will dramatically improve your productivity as a developer, system administrator, or power user. This comprehensive guide will take you from basic commands to advanced scripting techniques.

Table of Contents

  1. Getting Started with Bash
  2. Essential Commands
  3. File System Navigation
  4. Text Processing
  5. Variables and Environment
  6. Control Structures
  7. Functions
  8. I/O and Redirection
  9. Process Management
  10. Advanced Features
  11. Best Practices
  12. Common Pitfalls
  13. Conclusion

Getting Started with Bash

What is Bash?

Bash is both a command-line interface and a scripting language. It provides a powerful way to interact with your operating system, automate tasks, and create complex workflows.

Basic Syntax

Every Bash command follows this basic structure:

command [options] [arguments]
Enter fullscreen mode Exit fullscreen mode

For example:

ls -la /home/user
Enter fullscreen mode Exit fullscreen mode

Your First Script

Create a file with a .sh extension:

#!/bin/bash
echo "Hello, World!"
Enter fullscreen mode Exit fullscreen mode

Make it executable and run it:

chmod +x hello.sh
./hello.sh
Enter fullscreen mode Exit fullscreen mode

Essential Commands

File Operations

  • ls - List directory contents
  • cp - Copy files and directories
  • mv - Move/rename files and directories
  • rm - Remove files and directories
  • mkdir - Create directories
  • rmdir - Remove empty directories
  • find - Search for files and directories

Text Operations

  • cat - Display file contents
  • less/more - View file contents page by page
  • head - Display first lines of a file
  • tail - Display last lines of a file
  • grep - Search text patterns
  • sed - Stream editor for text manipulation
  • awk - Text processing tool

System Information

  • ps - Show running processes
  • top/htop - Display system processes
  • df - Show disk space usage
  • du - Show directory space usage
  • free - Show memory usage
  • uname - System information

File System Navigation

Basic Navigation

# Change directory
cd /path/to/directory
cd ~  # Go to home directory
cd -  # Go to previous directory

# Print working directory
pwd

# List with details
ls -la

# Show hidden files
ls -a
Enter fullscreen mode Exit fullscreen mode

Path Management

# Absolute path
/home/user/documents/file.txt

# Relative path
../documents/file.txt
./current-directory/file.txt

# Using wildcards
ls *.txt        # All .txt files
ls file?.txt    # file1.txt, fileA.txt, etc.
ls file[1-3].txt # file1.txt, file2.txt, file3.txt
Enter fullscreen mode Exit fullscreen mode

Text Processing

grep - Pattern Matching

# Basic search
grep "pattern" file.txt

# Case-insensitive search
grep -i "pattern" file.txt

# Recursive search
grep -r "pattern" /directory

# Show line numbers
grep -n "pattern" file.txt

# Invert match (show non-matching lines)
grep -v "pattern" file.txt
Enter fullscreen mode Exit fullscreen mode

sed - Stream Editor

# Replace first occurrence
sed 's/old/new/' file.txt

# Replace all occurrences
sed 's/old/new/g' file.txt

# Replace in-place
sed -i 's/old/new/g' file.txt

# Delete lines containing pattern
sed '/pattern/d' file.txt

# Print specific lines
sed -n '1,5p' file.txt  # Print lines 1-5
Enter fullscreen mode Exit fullscreen mode

awk - Text Processing

# Print specific columns
awk '{print $1, $3}' file.txt

# Print lines with condition
awk '$3 > 100' file.txt

# Sum a column
awk '{sum += $1} END {print sum}' file.txt

# Use custom delimiter
awk -F',' '{print $2}' file.csv
Enter fullscreen mode Exit fullscreen mode

Variables and Environment

Variable Declaration and Usage

# Declare variables (no spaces around =)
name="John"
age=25

# Use variables
echo "Hello, $name"
echo "You are ${age} years old"

# Command substitution
current_date=$(date)
file_count=`ls | wc -l`

# Read user input
read -p "Enter your name: " username
echo "Hello, $username"
Enter fullscreen mode Exit fullscreen mode

Environment Variables

# Common environment variables
echo $HOME      # Home directory
echo $PATH      # Executable paths
echo $USER      # Current user
echo $PWD       # Current directory

# Export variables to subshells
export MY_VAR="value"

# Set PATH
export PATH=$PATH:/new/directory
Enter fullscreen mode Exit fullscreen mode

Special Variables

$0  # Script name
$1, $2, $3  # Script arguments
$#  # Number of arguments
$@  # All arguments as separate strings
$*  # All arguments as single string
$$  # Process ID
$?  # Exit status of last command
Enter fullscreen mode Exit fullscreen mode

Control Structures

Conditional Statements

# if-else statement
if [ condition ]; then
    # commands
elif [ another_condition ]; then
    # commands
else
    # commands
fi

# Examples
if [ $age -gt 18 ]; then
    echo "Adult"
else
    echo "Minor"
fi

# String comparisons
if [ "$string1" = "$string2" ]; then
    echo "Strings match"
fi

# File tests
if [ -f "/path/to/file" ]; then
    echo "File exists"
fi

if [ -d "/path/to/directory" ]; then
    echo "Directory exists"
fi
Enter fullscreen mode Exit fullscreen mode

Loops

# for loop
for i in {1..10}; do
    echo $i
done

for file in *.txt; do
    echo "Processing $file"
done

# while loop
counter=1
while [ $counter -le 5 ]; do
    echo $counter
    ((counter++))
done

# until loop
until [ $counter -gt 10 ]; do
    echo $counter
    ((counter++))
done
Enter fullscreen mode Exit fullscreen mode

Case Statements

case $variable in
    pattern1)
        commands
        ;;
    pattern2|pattern3)
        commands
        ;;
    *)
        default commands
        ;;
esac

# Example
case $1 in
    start)
        echo "Starting service..."
        ;;
    stop)
        echo "Stopping service..."
        ;;
    restart)
        echo "Restarting service..."
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}"
        ;;
esac
Enter fullscreen mode Exit fullscreen mode

Functions

Function Definition

# Method 1
function_name() {
    # commands
    return 0  # optional return value
}

# Method 2
function function_name {
    # commands
}

# Example
greet() {
    local name=$1
    echo "Hello, $name!"
}

# Call function
greet "Alice"
Enter fullscreen mode Exit fullscreen mode

Function Parameters and Local Variables

calculate_sum() {
    local num1=$1
    local num2=$2
    local sum=$((num1 + num2))
    echo $sum
}

result=$(calculate_sum 5 3)
echo "Sum: $result"
Enter fullscreen mode Exit fullscreen mode

I\O and Redirection

Standard Streams

  • stdin (0) - Standard input
  • stdout (1) - Standard output
  • stderr (2) - Standard error

Redirection

# Redirect stdout to file
command > file.txt

# Append stdout to file
command >> file.txt

# Redirect stderr
command 2> error.log

# Redirect both stdout and stderr
command > output.txt 2>&1
command &> output.txt  # Bash 4+

# Redirect stdin
command < input.txt

# Here documents
cat << EOF
This is a here document
Multiple lines of text
EOF
Enter fullscreen mode Exit fullscreen mode

Pipes

# Basic pipe
command1 | command2

# Chain multiple commands
ps aux | grep python | grep -v grep

# Tee - write to file and stdout
command | tee output.txt

# Process substitution
diff <(ls dir1) <(ls dir2)
Enter fullscreen mode Exit fullscreen mode

Process Management

Background and Foreground Processes

# Run in background
command &

# List jobs
jobs

# Bring to foreground
fg %1

# Send to background
bg %1

# Disown process
disown %1
Enter fullscreen mode Exit fullscreen mode

Process Control

# Kill process by PID
kill 1234
kill -9 1234  # Force kill

# Kill by name
killall process_name
pkill process_name

# Process information
ps aux | grep process_name
pgrep process_name
Enter fullscreen mode Exit fullscreen mode

Command Execution Control

# Run commands sequentially
command1; command2; command3

# Run if previous succeeds
command1 && command2

# Run if previous fails
command1 || command2

# Group commands
(command1; command2) | command3
{ command1; command2; } | command3
Enter fullscreen mode Exit fullscreen mode

Advanced Features

Arrays

# Declare array
fruits=("apple" "banana" "orange")

# Access elements
echo ${fruits[0]}      # First element
echo ${fruits[@]}      # All elements
echo ${fruits[*]}      # All elements (different quoting behavior)
echo ${#fruits[@]}     # Array length

# Add elements
fruits+=("grape")

# Loop through array
for fruit in "${fruits[@]}"; do
    echo $fruit
done
Enter fullscreen mode Exit fullscreen mode

String Manipulation

string="Hello, World!"

# String length
echo ${#string}

# Substring
echo ${string:0:5}    # "Hello"
echo ${string:7}      # "World!"

# Replace
echo ${string/Hello/Hi}           # Replace first occurrence
echo ${string//o/0}               # Replace all occurrences

# Remove from beginning/end
filename="document.txt"
echo ${filename%.txt}             # Remove .txt extension
echo ${filename#*/}               # Remove everything up to first /
Enter fullscreen mode Exit fullscreen mode

Regular Expressions

# Pattern matching with [[ ]]
if [[ $string =~ ^[0-9]+$ ]]; then
    echo "String contains only digits"
fi

# Extended globbing
shopt -s extglob
ls *.@(jpg|png|gif)   # Files with jpg, png, or gif extensions
Enter fullscreen mode Exit fullscreen mode

Command Line Shortcuts

# History expansion
!!           # Last command
!n           # Command number n
!string      # Last command starting with string
^old^new     # Replace old with new in last command

# Tab completion
# Press Tab to complete commands, filenames, variables

# Brace expansion
echo {1..10}           # 1 2 3 4 5 6 7 8 9 10
echo {a..z}            # a b c d ... z
mkdir dir{1,2,3}       # Create dir1, dir2, dir3
Enter fullscreen mode Exit fullscreen mode

Best Practices

Script Structure

#!/bin/bash

# Script: backup.sh
# Description: Backup important files
# Author: Your Name
# Date: 2024-01-01

set -euo pipefail  # Exit on error, undefined variables, pipe failures

# Global variables
readonly BACKUP_DIR="/backup"
readonly LOG_FILE="/var/log/backup.log"

# Functions
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

main() {
    log "Starting backup process"
    # Main logic here
    log "Backup completed successfully"
}

# Check if running as root
if [[ $EUID -eq 0 ]]; then
    echo "Don't run this script as root"
    exit 1
fi

# Call main function
main "$@"
Enter fullscreen mode Exit fullscreen mode

Error Handling

# Check command success
if ! command -v git &> /dev/null; then
    echo "Git is not installed"
    exit 1
fi

# Trap for cleanup
cleanup() {
    echo "Cleaning up temporary files"
    rm -f /tmp/tempfile*
}
trap cleanup EXIT

# Validate arguments
if [[ $# -lt 2 ]]; then
    echo "Usage: $0 <source> <destination>"
    exit 1
fi
Enter fullscreen mode Exit fullscreen mode

Security Considerations

# Quote variables to prevent word splitting
cp "$file" "$destination"

# Use arrays for commands with spaces
command=("rsync" "-av" "--delete")
"${command[@]}" "$source/" "$destination/"

# Validate input
read -p "Enter filename: " filename
if [[ ! "$filename" =~ ^[a-zA-Z0-9._-]+$ ]]; then
    echo "Invalid filename"
    exit 1
fi
Enter fullscreen mode Exit fullscreen mode

Common Pitfalls

Quoting Issues

# Wrong - word splitting occurs
for file in $(ls *.txt); do
    echo $file
done

# Right - proper quoting
while IFS= read -r -d '' file; do
    echo "$file"
done < <(find . -name "*.txt" -print0)
Enter fullscreen mode Exit fullscreen mode

Variable Scope

# Global variable modified in subshell
counter=0
cat file.txt | while read line; do
    ((counter++))
done
echo $counter  # Still 0!

# Solution: use process substitution
counter=0
while read line; do
    ((counter++))
done < <(cat file.txt)
echo $counter  # Correct value
Enter fullscreen mode Exit fullscreen mode

File Testing

# Wrong - doesn't handle spaces in filenames
if [ -f $file ]; then

# Right - proper quoting
if [[ -f "$file" ]]; then
Enter fullscreen mode Exit fullscreen mode

Conclusion

Mastering Bash is a journey that pays dividends in productivity and system understanding. Start with the basics and gradually incorporate advanced features into your workflow. Practice regularly, read existing scripts, and don't hesitate to experiment in a safe environment.

Remember these key principles:

  • Always quote your variables
  • Use set -euo pipefail for robust scripts
  • Handle errors gracefully
  • Write readable, well-commented code
  • Test your scripts thoroughly

With these skills and practices, you'll be well on your way to becoming a Bash expert. The command line will transform from a intimidating interface into a powerful ally in your daily computing tasks.

And as always please feel free to criticize this article and share your thoughts! Cheers

Top comments (0)