bash Compatibility Reference
June 6, 2026 ยท View on GitHub
This document details brush's compatibility with bash, including supported features, known limitations, and how to report issues.
Overview
brush aims for high compatibility with bash. We validate this through 1700+ compatibility test cases that compare behavior against bash as an oracle.
Compatibility snapshot: Production-ready for most use cases. Your .bashrc, aliases, functions, and completions should "just work."
Fully Supported Features โ
Shell Syntax & Control Flow
if/then/elif/else/ficonditionalsfor,while,untilloops- Arithmetic
forloops:for ((i=0; i<10; i++)) case/esacpattern matching&&,||conditional execution- Subshells
()and command grouping{} - Pipelines and pipeline negation
! - Coprocesses:
coproc { ... }andcoproc NAME { ... }
Expansions
- Brace expansion:
{a,b,c},{1..10},{a..z} - Parameter expansion:
${var:-default},${var:+set},${var#pattern},${var%pattern},${var//find/replace}, etc. - Command substitution:
$(cmd),`cmd` - Arithmetic expansion:
$((expr)) - Process substitution:
<(cmd),>(cmd) - Tilde expansion:
~,~user - Globbing:
*,?,[...] - Extended globbing:
?(pat),*(pat),+(pat),@(pat),!(pat) globstar:**recursive matching
Builtins (50+)
- I/O:
echo,printf,read,mapfile/readarray - Variables:
declare,local,export,unset,readonly,typeset - Control:
break,continue,return,exit - Navigation:
cd,pushd,popd,dirs,pwd - Jobs:
jobs,fg,bg,wait,kill - Completion:
complete,compgen,compopt - History:
history,fc - Testing:
test,[,[[ - Sourcing & introspection:
.,source,eval,caller - Misc:
alias,unalias,hash,type,command,builtin,enable,help,times,ulimit,umask,trap,shopt,set,shift,getopts
Arrays
- Indexed arrays:
arr=(a b c),${arr[0]},${arr[@]} - Associative arrays:
declare -A map - Array slicing:
${arr[@]:start:length} - Array operations:
${#arr[@]},${!arr[@]},${!arr[*]}
Job Control
- Background execution:
cmd & - Suspend/resume: Ctrl+Z,
fg,bg - Job listing:
jobs - Process groups and pipelines
Dynamic Variables
RANDOM,SRANDOMLINENO,FUNCNAME,BASH_SOURCEEPOCHSECONDS,EPOCHREALTIMESECONDSPWD,OLDPWDBASH_VERSINFO,BASH_VERSION
Programmable Completion
- Compatible with
bash-completion - Git, Docker, systemctl, etc. completions work out of the box
complete,compgen,compoptbuiltins
Redirection
- Standard:
>,>>,<,2>&1 - Here documents:
<<EOF,<<-EOF(tab-stripped),<<<(here strings) - File descriptor manipulation:
>&n,<&n,n>&m - Process substitution redirects:
>(cmd),<(cmd) - Clobber control:
>|,set -o noclobber
Partially Supported Features ๐ท
Traps
| Status | Feature |
|---|---|
| โ | DEBUG trap |
| โ | ERR trap |
| โ | EXIT trap |
| ๐ท | Signal traps (SIGINT, SIGTERM, etc.) โ in progress |
Key Bindings (bind)
| Status | Feature |
|---|---|
| โ | Basic bind support |
| โ | bind -x for custom key-bound commands |
| ๐ท | Advanced bind features โ in progress |
Shell Options
| Status | Feature |
|---|---|
| โ | Common options: errexit, pipefail, extglob, globstar, noclobber, nounset, failglob |
| ๐ท | Less common options โ in progress |
Not Yet Supported Features ๐ง
These features are on our roadmap but not yet implemented:
select Statement
The select builtin for creating menu-driven scripts is not yet implemented.
# Not yet supported
select opt in "Option A" "Option B" "Quit"; do
case $opt in
"Option A") echo "A";;
"Option B") echo "B";;
"Quit") break;;
esac
done
wait -n
The wait -n option to wait for the next background job to complete is not implemented.
# Not yet supported
job1 &
job2 &
wait -n # Wait for whichever finishes first
$! for Background Commands
Bash expands $! to the process ID of the most recent asynchronous command.
Brush currently does not reliably provide this value for background commands,
so scripts that start a job with cmd & and immediately use $! may see an
empty value.
# Not yet fully supported
sleep 10 &
kill "$!"
BASH_COMMAND Variable
The special variable BASH_COMMAND that contains the currently executing command is currently only available in trap contexts.
disown and logout
These job control builtins are not yet implemented.
Known Edge Cases
These areas have known differences from bash in edge cases. Most users won't encounter these, but they're documented for completeness.
IFS (Input Field Separator)
There are ~10 known edge cases where IFS word splitting behavior differs from bash, particularly around:
- Non-whitespace IFS characters and empty field creation
- Mixed whitespace and non-whitespace IFS
- Leading/trailing delimiter handling
printf Format Specifiers
Some advanced printf format specifiers behave differently (~8 known cases), particularly features not supported by the underlying uucore library.
Arithmetic Expressions
- Division by zero handling may differ in
errexitmode $(( exit N ))syntax edge case
Aliases
Some complex alias expansion scenarios differ from bash (see GitHub issues #57, #286).
Test Suite Statistics
- Total test cases: 1700+
- Known failures: ~125
- Most failures are edge cases in IFS handling and printf
The test suite runs on every PR and compares behavior against bash as an oracle.
Version Compatibility
brush targets compatibility with bash 5.3+. Behavior may differ from older bash versions (3.x, 4.x) in some areas.
Reporting Compatibility Issues
Found a script that works in bash but not in brush?
- Check existing issues: GitHub Issues
- Create a minimal reproducer: Reduce to the smallest failing script
- File an issue with:
- The script or command that fails
- Expected behavior (what
bashdoes) - Actual behavior (what
brushdoes) - Your platform (Linux/macOS/etc.)
Tracking Progress
- GitHub Issues: Track specific compatibility work
- Test Suite: 1700+ tests run on every PR
- This Document: Updated as features are implemented