From bash-expert
Bash 5.3 new features and modern patterns (2025). PROACTIVELY activate for: (1) Bash 5.3 specific features (BASH_TRAPSIG, in-shell command substitution, ${|} REPLY syntax), (2) checking bash version compatibility, (3) migrating scripts to take advantage of 5.3 additions, (4) C23 conformance changes in bash 5.3, (5) new shopt and bind options, (6) trap handling improvements, (7) wait -p enhancements, (8) READLINE_ARGUMENT and history expansion changes. Provides: complete 5.3 feature reference, version-detection snippets, compatibility shims for older bash, migration recipes, and POSIX.1-2024 alignment notes.
How this skill is triggered — by the user, by Claude, or both
Slash command
/bash-expert:bash-53-featuresThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**MANDATORY: Always Use Backslashes on Windows for File Paths**
MANDATORY: Always Use Backslashes on Windows for File Paths
When using Edit or Write tools on Windows, you MUST use backslashes (\) in file paths, NOT forward slashes (/).
Examples:
D:/repos/project/file.tsxD:\repos\project\file.tsxThis applies to:
NEVER create new documentation files unless explicitly requested by the user.
Bash 5.3 (released July 2025) introduces significant new features that improve performance, readability, and functionality.
New: ${ command; } syntax - Executes without forking a subshell (runs in current shell context):
# OLD way (Bash < 5.3) - Creates subshell
output=$(expensive_command)
# NEW way (Bash 5.3+) - Runs in current shell, faster
output=${ expensive_command; }
Benefits:
Example:
#!/usr/bin/env bash
# Traditional approach
count=0
for file in *.txt; do
lines=$(wc -l < "$file") # Subshell created
((count += lines))
done
# Bash 5.3 approach (faster)
count=0
for file in *.txt; do
lines=${ wc -l < "$file"; } # No subshell
((count += lines))
done
New: ${| command; } syntax - Stores result in REPLY variable:
# Runs command, result goes to $REPLY automatically
${| complex_calculation; }
echo "Result: $REPLY"
# Multiple operations
${|
local_var="processing"
echo "$local_var: $((42 * 2))"
}
echo "Got: $REPLY"
Use Cases:
read BuiltinNew: -E option - Uses readline with programmable completion:
# Interactive input with tab completion
read -E -p "Enter filename: " filename
# User can now tab-complete file paths!
# With custom completion
read -E -p "Select environment: " env
# Enables full readline features (history, editing)
Benefits:
source BuiltinNew: -p PATH option - Custom search path for sourcing:
# OLD way
source /opt/myapp/lib/helpers.sh
# NEW way - Search custom path
source -p /opt/myapp/lib:/usr/local/lib helpers.sh
# Respects CUSTOM_PATH instead of current directory
CUSTOM_PATH=/app/modules:/shared/lib
source -p "$CUSTOM_PATH" database.sh
Benefits:
compgen BuiltinNew: Variable output option - Store completions in variable:
# OLD way - Output to stdout
completions=$(compgen -f)
# NEW way - Directly to variable
compgen -v completions_var -f
# Results now in $completions_var
Benefits:
New: Control glob sorting behavior:
# Default: alphabetical sort
echo *.txt
# Sort by modification time (newest first)
GLOBSORT="-mtime"
echo *.txt
# Sort by size
GLOBSORT="size"
echo *.txt
# Reverse alphabetical
GLOBSORT="reverse"
echo *.txt
Options:
name - Alphabetical (default)reverse - Reverse alphabeticalsize - By file sizemtime - By modification time-mtime - Reverse modification timeNew: Signal number variable in traps:
#!/usr/bin/env bash
set -euo pipefail
# BASH_TRAPSIG contains the signal number being handled
handle_signal() {
echo "Caught signal: $BASH_TRAPSIG" >&2
case "$BASH_TRAPSIG" in
15) echo "SIGTERM (15) received, shutting down gracefully" ;;
2) echo "SIGINT (2) received, cleaning up" ;;
*) echo "Signal $BASH_TRAPSIG received" ;;
esac
}
trap handle_signal SIGTERM SIGINT SIGHUP
Benefits:
New: fltexpr loadable builtin:
# Enable floating-point support
enable -f /usr/lib/bash/fltexpr fltexpr
# Perform calculations
fltexpr result = 42.5 * 1.5
echo "$result" # 63.75
# Complex expressions
fltexpr pi_area = 3.14159 * 5 * 5
echo "Area: $pi_area"
Use Cases:
# ❌ OLD (Bash < 5.3) - Multiple subshells
for i in {1..1000}; do
result=$(echo "$i * 2" | bc)
process "$result"
done
# ✅ NEW (Bash 5.3+) - No subshells
for i in {1..1000}; do
result=${ echo $((i * 2)); }
process "$result"
done
Performance Gain: ~40% faster in benchmarks
#!/usr/bin/env bash
# Process large file efficiently
process_log() {
local line_count=0
local error_count=0
while IFS= read -r line; do
((line_count++))
# Bash 5.3: No subshell for grep
if ${ grep -q "ERROR" <<< "$line"; }; then
((error_count++))
fi
done < "$1"
echo "Processed $line_count lines, found $error_count errors"
}
process_log /var/log/app.log
#!/usr/bin/env bash
# Require Bash 5.3+
if ((BASH_VERSINFO[0] < 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] < 3))); then
echo "Error: Bash 5.3+ required (found $BASH_VERSION)" >&2
exit 1
fi
# Test for 5.3 features
has_bash_53_features() {
# Try using ${ } syntax
if eval 'test=${ echo "yes"; }' 2>/dev/null; then
return 0
else
return 1
fi
}
if has_bash_53_features; then
echo "Bash 5.3 features available"
else
echo "Using legacy mode"
fi
#!/usr/bin/env bash
set -euo pipefail
# Support both old and new bash
if ((BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3))); then
# Bash 5.3+ path
result=${ compute_value; }
else
# Legacy path
result=$(compute_value)
fi
Use ${ } for performance-critical loops
for item in "${large_array[@]}"; do
processed=${ transform "$item"; }
done
Use ${| } for clean temporary values
${| calculate_hash "$file"; }
if [[ "$REPLY" == "$expected_hash" ]]; then
echo "Valid"
fi
Enable readline for interactive scripts
read -E -p "Config file: " config
Use source -p for modular libraries
source -p "$LIB_PATH" database.sh logging.sh
Document version requirements
# Requires: Bash 5.3+ for performance features
Note: Bash 5.3 (released July 2025) is the latest stable version. There is no Bash 5.4 as of October 2025.
brew install bash)bash:5.3 official imageBash 5.3 updated to C23 language standard. Note: K&R style C compilers are no longer supported.
#!/usr/bin/env bash
set -euo pipefail
# Detect bash version
readonly BASH_53_PLUS=$((BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3)))
process_items() {
local item
for item in "$@"; do
if ((BASH_53_PLUS)); then
result=${ transform "$item"; } # Fast path
else
result=$(transform "$item") # Compatible path
fi
echo "$result"
done
}
#!/usr/bin/env bash
set -euo pipefail
# Parse log file (Bash 5.3 optimized)
parse_log() {
local file="$1"
local stats_errors=0
local stats_warnings=0
local stats_lines=0
while IFS= read -r line; do
((stats_lines++))
# Fast pattern matching (no subshell)
${| grep -q "ERROR" <<< "$line"; } && ((stats_errors++))
${| grep -q "WARN" <<< "$line"; } && ((stats_warnings++))
done < "$file"
echo "Lines: $stats_lines, Errors: $stats_errors, Warnings: $stats_warnings"
}
parse_log /var/log/application.log
#!/usr/bin/env bash
set -euo pipefail
# Interactive setup with readline
setup_config() {
echo "Configuration Setup"
echo "==================="
# Tab completion for paths
read -E -p "Data directory: " data_dir
read -E -p "Config file: " config_file
# Validate and store
${|
[[ -d "$data_dir" ]] && echo "valid" || echo "invalid"
}
if [[ "$REPLY" == "valid" ]]; then
echo "DATA_DIR=$data_dir" > config.env
echo "CONFIG_FILE=$config_file" >> config.env
echo "✓ Configuration saved"
else
echo "✗ Invalid directory" >&2
return 1
fi
}
setup_config
Bash 5.3 provides significant performance and usability improvements. Adopt these features gradually while maintaining backwards compatibility for older systems.
npx claudepluginhub thimslugga/thimslugga-cc-plugins --plugin bash-expertGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.