Przejdź do treści

🐚 Bash Differences Reference

Understanding the differences between Bash and other shells is crucial for writing portable scripts and leveraging Bash-specific features effectively. This reference highlights key distinctions and capabilities.


🎯 Major Bash Features

Arrays

Bash supports indexed and associative arrays, unlike POSIX sh.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Indexed arrays (Bash 2.0+)
fruits=("apple" "banana" "cherry")
fruits[3]="date"
echo "${fruits[0]}"        # apple
echo "${fruits[@]}"        # all elements
echo "${#fruits[@]}"       # array length

# Associative arrays (Bash 4.0+)
declare -A userinfo
userinfo[name]="John"
userinfo[age]=30
echo "${userinfo[name]}"

Advanced Parameter Expansion

Extended parameter manipulation capabilities.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var="Hello World"

# Case conversion (Bash 4.0+)
echo "${var^^}"           # HELLO WORLD (upper)
echo "${var,,}"           # hello world (lower)

# Pattern removal
echo "${var#Hello }"      # World (remove shortest from front)
echo "${var##Hello }"     # World (remove longest from front)
echo "${var% World}"      # Hello (remove shortest from back)
echo "${var%% World}"     # Hello (remove longest from back)

# Pattern replacement
echo "${var/World/Universe}"  # Hello Universe
echo "${var//o/O}"           # HellO WOrld (global replace)

Extended Test Conditions

Enhanced conditional expressions with [[ ]].

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Pattern matching
if [[ "$file" == *.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

# String operations
if [[ -n "$string" && "$string" != "test" ]]; then
    echo "Valid string"
fi

🔧 Process Management Extensions

Process Substitution

Execute commands and treat output as files.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Compare sorted outputs
diff <(sort file1.txt) <(sort file2.txt)

# Read from command output
while read line; do
    echo "Processing: $line"
done < <(find . -name "*.log")

# Write to command input
cat > >(gzip > output.gz) << EOF
Large content here
EOF

Coprocesses

Bidirectional communication with background processes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Start coprocess
coproc SORT { sort; }

# Send data
echo "banana" >&"${SORT[1]}"
echo "apple" >&"${SORT[1]}"
echo "cherry" >&"${SORT[1]}"

# Close input
exec {SORT[1]}>&-

# Read results
while read line <&"${SORT[0]}"; do
    echo "Sorted: $line"
done

📊 Advanced I/O Features

Here Strings

Pass strings directly as input.

1
2
3
4
5
# Instead of echo "string" | command
grep "pattern" <<< "search in this string"

# Multiple lines
wc -l <<< $'line1\nline2\nline3'

Redirection Enhancements

Advanced redirection capabilities.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Redirect to multiple outputs
tee >(gzip > file.log.gz) >(logger -t myapp) > file.log

# Close file descriptors
exec 3<&-  # Close FD 3

# Move file descriptors
exec 3<&0  # Save stdin to FD 3
exec 0</dev/null  # Redirect stdin to /dev/null
exec 0<&3  # Restore stdin from FD 3
exec 3<&-  # Close FD 3

🎨 Programming Constructs

Function Features

Enhanced function capabilities.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Local variables with assignment
myfunc() {
    local var="local value"
    local assigned_var
    assigned_var=$(date)
    echo "$var - $assigned_var"
}

# Function attributes (Bash 4.2+)
readonly -f myfunc  # Make function readonly

# Function recursion with local scope
factorial() {
    local n=$1
    if (( n <= 1 )); then
        echo 1
    else
        local n_minus_one=$((n - 1))
        local sub_result
        sub_result=$(factorial $n_minus_one)
        echo $((n * sub_result))
    fi
}

Arithmetic Evaluation

Advanced mathematical operations.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Arithmetic evaluation with (( ))
x=5
if (( x > 3 && x < 10 )); then
    echo "x is between 3 and 10"
fi

# Bitwise operations
(( result = 5 << 2 ))  # Left shift: 20
(( result = 15 & 7 ))  # Bitwise AND: 7

# Increment/decrement
(( x++ ))
(( ++y ))

# Compound assignments
(( x += 5 ))
(( y *= 2 ))

🔍 Pattern Matching and Globbing

Extended Globbing

Advanced pattern matching features.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Enable extended globbing
shopt -s extglob

# Extended patterns
ls !(pattern)      # Not matching pattern
ls +(pattern)      # One or more occurrences
ls *(pattern)      # Zero or more occurrences
ls ?(pattern)      # Zero or one occurrence
ls @(pattern1|pattern2)  # Either pattern1 or pattern2

# Example
ls !(test*|*.tmp)  # All files except those starting with test or ending with .tmp

Brace Expansion

Generate arbitrary strings.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Simple sequences
echo {1..10}        # 1 2 3 4 5 6 7 8 9 10
echo {a..z}         # a b c ... x y z

# Zero-padded sequences
echo {01..10}       # 01 02 03 ... 09 10

# Nested brace expansion
echo {a,b}{1,2}     # a1 a2 b1 b2

# Combining with other text
echo file{1..3}.txt  # file1.txt file2.txt file3.txt

🛠️ Bash-Specific Builtins

Advanced Builtins

Bash-specific command-line utilities.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Complete - programmable completion
complete -F _my_completion mycommand

# Coproc - coprocess management
coproc myproc { while read line; do echo "Got: $line"; done; }

# Disown - remove jobs from job table
long_running_command &
disown %1

# Hash - remember command locations
hash -p /custom/path/command custom_command

# Jobs - job control
jobs -l  # List jobs with PIDs
jobs -r  # List running jobs
jobs -s  # List stopped jobs

Shell Options

Bash-specific shell behavior control.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Useful shopt options
shopt -s cdspell        # Correct minor spelling errors in cd
shopt -s checkwinsize   # Check window size after each command
shopt -s cmdhist        # Save multi-line commands in history
shopt -s dotglob        # Include dotfiles in pathname expansion
shopt -s expand_aliases # Expand aliases
shopt -s extglob        # Enable extended pattern matching
shopt -s failglob       # Fail on unmatched globs
shopt -s globstar       # Enable ** globbing (Bash 4.0+)
shopt -s histappend     # Append to history file
shopt -s interactive_comments  # Allow comments in interactive mode

📋 Version-Specific Features

Bash 4.x Features

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# Associative arrays
declare -A config
config[database]="mysql"
config[port]=3306

# Case conversion
name="John Doe"
echo "${name,,}"  # john doe
echo "${name^^}"  # JOHN DOE

# Globstar
shopt -s globstar
for file in **/*.txt; do
    echo "$file"
done

# nameref (Bash 4.3+)
declare -n ref=original_var
ref="new value"  # Modifies original_var

Bash 5.x Features

1
2
3
4
5
6
7
8
9
# Array slice assignment
arr=(a b c d e)
arr[1...3]=("x" "y" "z")  # Assign to indices 1,2,3

# Improved error messages
# Better diagnostic information for various error conditions

# Enhanced programmable completion
# More flexible completion functions

⚠️ Bashisms to Avoid for Portability

Non-Portable Features

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# ❌ Arrays (use delimited strings instead)
items=(item1 item2 item3)

# ✅ Portable alternative
ITEMS="item1,item2,item3"
IFS=',' read -ra item_array <<< "$ITEMS"

# ❌ [[ ]] (use [ ] instead)
if [[ "$var" == pattern ]]; then

# ✅ Portable alternative
case "$var" in
    pattern)
        # match action
        ;;
esac

# ❌ Process substitution
diff <(sort file1) <(sort file2)

# ✅ Portable alternative
temp1=$(mktemp)
temp2=$(mktemp)
sort file1 > "$temp1"
sort file2 > "$temp2"
diff "$temp1" "$temp2"
rm "$temp1" "$temp2"

# ❌ Extended parameter expansion
echo "${var^^}"

# ✅ Portable alternative
echo "$var" | tr '[:lower:]' '[:upper:]'

🧾 Summary Comparison

Feature Matrix

Feature Bash POSIX sh ksh zsh
Arrays ✅ Indexed/Associative ✅ Indexed ✅ Indexed/Associative
[[ ]]
Process Substitution
Extended Globbing ✅ (extglob)
Brace Expansion Limited
Here Strings
Coprocesses
Case Conversion Bash 4.0+
Name References Bash 4.3+

When to Use Bash Features

Use Bash-specific features when: - Targeting Bash environments specifically - Need advanced array operations - Require pattern matching beyond basic globbing - Want improved error handling and debugging - Leveraging interactive shell enhancements

Avoid Bash-specific features when: - Writing portable scripts for multiple systems - Targeting minimal environments (containers, embedded) - Need maximum compatibility with other shells - Following strict POSIX compliance requirements


🧠 Best Practices

Bash Usage Guidelines

  1. Explicit Shell Declaration: Use #!/bin/bash for Bash-specific scripts
  2. Version Checking: Check Bash version for newer features
  3. Feature Testing: Use shopt and conditional checks
  4. Documentation: Clearly document Bash-specific requirements
  5. Fallbacks: Provide portable alternatives when possible
  6. Testing: Test across different Bash versions
  7. Security: Be cautious with dynamic features like eval

Version Compatibility Check

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Check Bash version
if [[ ${BASH_VERSION%%.*} -lt 4 ]]; then
    echo "Bash 4.0 or higher required" >&2
    exit 1
fi

# Check for specific features
if ! shopt -q extglob; then
    shopt -s extglob
fi

🧾 See Also