Bash Features

Bash offers a rich set of features that make it powerful for both interactive use and scripting. Understanding these features will help you write more efficient and effective scripts.

Interactive Features

Command History

Bash maintains a history of commands you’ve executed:

# View command history
$ history
1001  ls -la
1002  cd /home
1003  pwd
1004  echo "hello world"
1005  history

# Execute previous command
$ !!

# Execute command by number
$ !1003

# Search history
$ !pw
pwd

# Reverse search (Ctrl+R)
(reverse-i-search)`ls': ls -la

History Configuration

# In ~/.bashrc
HISTSIZE=1000          # Commands in memory
HISTFILESIZE=2000      # Commands in history file
HISTCONTROL=ignoredups # Ignore duplicate commands

# Don't save certain commands
HISTIGNORE="ls:pwd:exit:clear"

Tab Completion

Bash provides intelligent tab completion:

# Complete commands
$ ec<TAB>
echo

# Complete file names
$ ls /usr/b<TAB>
bin/

# Complete variable names
$ echo $HO<TAB>
$HOME

# Complete options
$ ls --<TAB><TAB>
--all                    --escape
--almost-all            --file-type
--author                --format

Custom Completion

# Add to ~/.bashrc
complete -W "start stop restart status" service
complete -d cd  # Only directories for cd

Command Line Editing

Bash uses readline library for command editing:

# Cursor movement
Ctrl+A    # Beginning of line
Ctrl+E    # End of line
Ctrl+B    # Back one character
Ctrl+F    # Forward one character
Alt+B     # Back one word
Alt+F     # Forward one word

# Editing
Ctrl+D    # Delete character under cursor
Ctrl+H    # Delete character before cursor
Ctrl+K    # Kill from cursor to end of line
Ctrl+U    # Kill from cursor to beginning of line
Ctrl+W    # Kill word before cursor
Alt+D     # Kill word after cursor

# History navigation
Ctrl+P    # Previous command
Ctrl+N    # Next command
Ctrl+R    # Reverse search

Job Control

Bash provides sophisticated job control capabilities:

Background Jobs

# Run command in background
$ long_running_command &
[1] 12345

# List active jobs
$ jobs
[1]+  Running    long_running_command &

# Bring job to foreground
$ fg %1

# Send job to background
$ bg %1

Job Management

#!/bin/bash
# job_control_demo.sh

echo "Starting background jobs..."

# Start multiple background jobs
sleep 30 &
job1=$!

sleep 40 &
job2=$!

echo "Job 1 PID: $job1"
echo "Job 2 PID: $job2"

# Wait for specific job
wait $job1
echo "Job 1 completed"

# Wait for all background jobs
wait
echo "All jobs completed"

Process Control

# Suspend current process
Ctrl+Z

# Kill current process
Ctrl+C

# Send signals to processes
$ kill -TERM 12345
$ kill -KILL 12345
$ killall process_name

Aliases and Functions

Aliases

Simple command shortcuts:

# Define aliases
alias ll='ls -la'
alias la='ls -A'
alias l='ls -CF'
alias grep='grep --color=auto'

# Use aliases
$ ll
total 24
drwxr-xr-x  3 user user 4096 Jan 15 10:30 .
drwxr-xr-x 25 user user 4096 Jan 15 10:25 ..

# List all aliases
$ alias

# Remove alias
$ unalias ll

Functions

More complex reusable code:

# Simple function
greet() {
    echo "Hello, $1!"
}

# Function with multiple parameters
backup_file() {
    local file="$1"
    local backup_dir="$2"

    if [ -f "$file" ]; then
        cp "$file" "$backup_dir/$(basename "$file").bak"
        echo "Backed up $file"
    else
        echo "File $file not found"
        return 1
    fi
}

# Use functions
$ greet "World"
Hello, World!

$ backup_file "/etc/hosts" "/backup"
Backed up /etc/hosts

Variable Features

Variable Types

# Regular variables
name="John"
age=25

# Arrays
fruits=("apple" "banana" "orange")
echo ${fruits[0]}  # apple
echo ${fruits[@]}  # all elements

# Associative arrays (Bash 4+)
declare -A colors
colors[red]="#FF0000"
colors[green]="#00FF00"
echo ${colors[red]}  # #FF0000

Parameter Expansion

filename="document.txt"

# Basic expansion
echo $filename          # document.txt
echo ${filename}        # document.txt

# Length
echo ${#filename}       # 12

# Substring
echo ${filename:0:8}    # document

# Remove from end
echo ${filename%.*}     # document

# Remove from beginning
echo ${filename##*.}    # txt

# Replace
echo ${filename/txt/pdf}  # document.pdf

Default Values

# Use default if variable is unset
echo ${name:-"Anonymous"}

# Set default if variable is unset
echo ${name:="Default Name"}

# Error if variable is unset
echo ${name:?"Variable name is required"}

# Use alternative if variable is set
echo ${name:+"Name is set"}

Pattern Matching and Globbing

Basic Wildcards

# Match any characters
$ ls *.txt
file1.txt  file2.txt  document.txt

# Match single character
$ ls file?.txt
file1.txt  file2.txt

# Match character ranges
$ ls file[1-3].txt
file1.txt  file2.txt  file3.txt

# Match character sets
$ ls file[abc].txt
filea.txt  fileb.txt  filec.txt

Extended Globbing

# Enable extended globbing
shopt -s extglob

# Match one of several patterns
$ ls *.@(txt|pdf|doc)

# Match zero or one occurrence
$ ls file?(s).txt

# Match zero or more occurrences
$ ls file*(s).txt

# Match one or more occurrences
$ ls file+(s).txt

# Match anything except pattern
$ ls !(*.tmp)

Globstar (Bash 4+)

# Enable globstar
shopt -s globstar

# Recursive matching
$ ls **/*.txt
dir1/file1.txt
dir1/subdir/file2.txt
dir2/file3.txt

Brace Expansion

Sequence Generation

# Number sequences
$ echo {1..10}
1 2 3 4 5 6 7 8 9 10

$ echo {01..10}
01 02 03 04 05 06 07 08 09 10

# Letter sequences
$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z

# Step sequences (Bash 4+)
$ echo {1..10..2}
1 3 5 7 9

String Expansion

# Multiple strings
$ echo {cat,dog,bird}
cat dog bird

# Combinations
$ echo {a,b}{1,2}
a1 a2 b1 b2

# File operations
$ cp file.txt{,.bak}  # Same as: cp file.txt file.txt.bak
$ mkdir -p project/{src,docs,tests}

Process Substitution

Input Substitution

# Compare output of two commands
$ diff <(ls dir1) <(ls dir2)

# Use command output as input
$ while read line; do
    echo "Processing: $line"
done < <(find /var/log -name "*.log")

Output Substitution

# Send output to multiple commands
$ echo "data" | tee >(command1) >(command2)

# Log to file and display
$ make 2>&1 | tee >(logger -t build)

Command Substitution

Modern Syntax

# Preferred method
current_date=$(date)
file_count=$(ls | wc -l)
user_home=$(eval echo ~$USER)

echo "Today is $current_date"
echo "Files in directory: $file_count"

Legacy Syntax

# Older method (still works)
current_date=`date`
file_count=`ls | wc -l`

Nested Substitution

# Complex nested commands
backup_name="backup_$(date +%Y%m%d)_$(hostname).tar.gz"
echo $backup_name  # backup_20240115_myserver.tar.gz

Arithmetic Operations

Arithmetic Expansion

# Basic arithmetic
result=$((5 + 3))
echo $result  # 8

# Variables in arithmetic
a=10
b=5
echo $((a + b))   # 15
echo $((a * b))   # 50
echo $((a / b))   # 2
echo $((a % b))   # 0

Arithmetic Commands

# let command
let "result = 5 + 3"
echo $result  # 8

# expr command (external)
result=$(expr 5 + 3)
echo $result  # 8

Advanced Arithmetic

# Increment/decrement
counter=0
((counter++))
echo $counter  # 1

((counter += 5))
echo $counter  # 6

# Comparison in arithmetic
if ((counter > 5)); then
    echo "Counter is greater than 5"
fi

Conditional Expressions

Test Command

# File tests
if [ -f "file.txt" ]; then
    echo "File exists"
fi

# String tests
if [ "$name" = "John" ]; then
    echo "Hello John"
fi

# Numeric tests
if [ $age -gt 18 ]; then
    echo "Adult"
fi

Extended Test

# Bash extended test
if [[ $name == "John" ]]; then
    echo "Hello John"
fi

# Pattern matching
if [[ $filename == *.txt ]]; then
    echo "Text file"
fi

# Regular expressions
if [[ $email =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
    echo "Valid email"
fi

I/O Redirection

Basic Redirection

# Redirect stdout
$ echo "Hello" > file.txt

# Redirect stderr
$ command 2> error.log

# Redirect both
$ command > output.log 2>&1
$ command &> output.log  # Bash shortcut

Advanced Redirection

# Append to file
$ echo "More data" >> file.txt

# Here documents
$ cat << EOF > config.txt
Setting1=value1
Setting2=value2
EOF

# Here strings
$ grep "pattern" <<< "$variable"

Shell Options

Set Options

# Exit on error
set -e

# Exit on undefined variable
set -u

# Exit on pipe failure
set -o pipefail

# Combine options
set -euo pipefail

Shopt Options

# Enable extended globbing
shopt -s extglob

# Enable case-insensitive globbing
shopt -s nocaseglob

# Enable recursive globbing
shopt -s globstar

# List all options
shopt

These features make Bash a powerful and flexible shell for both interactive use and scripting. Understanding and utilizing these features will significantly improve your productivity and the quality of your scripts.