Bash Compatibility & Scripting¶
hellish runs real scripts โ not a toy REPL. Status legend: โ shipped ยท ๐ง in progress ยท ๐ planned
The proof: it built a Linux distribution¶
The strongest compatibility claim a shell can make isn't a feature list โ it's running real-world
scripts. hellish was used as the build-script interpreter for a complete Linux From Scratch
build: it drove ./configure, autotools, gcc/glibc/binutils, and ~80 packages, producing a disk
image that boots (uname -r โ 6.6.32-dlesieur, network up, SysVinit, clean shutdown).
Most "write your own shell" projects die on the first ./configure. hellish built an OS. That's the
bar this page documents against.
Feature matrix vs. bash¶
| Area | Feature | Status |
|---|---|---|
| Control flow | if/for/while/until/case, functions, &&/\|\|/;/! |
โ |
| Pipelines/redir | pipes, >/>>/<, 2>&1, fd dup, subshells ( ), groups { } |
โ |
| Conditionals | [[ โฆ ]] (string/int/file/unary, &&/\|\|/!/( ), ==), [ ]/test |
โ |
| Substitution | $(โฆ) / backticks, arithmetic $(( โฆ )) (++ -- += ?: , , bases) |
โ |
| Heredocs | <<, <<-, quoted & unquoted, ${VAR} bodies, consecutive, in-function |
โ |
| Process subst. | <(โฆ), >(โฆ), exec > >(tee โฆ) |
โ |
| Parameter exp. | ${v:-w} ${v:+w} ${#v} ${v#p} ${v%p}, substring, positional |
โ |
| Brace expansion | {a,b,c}, {1..n}, with $var/quoted prefixes |
โ |
| Globbing | * ? [โฆ], sorted matches, no-match passthrough |
โ |
| Options/traps | set -o pipefail, set -e/-u/-o, trap (EXIT/INT/TERM) |
โ |
| Job control | bg/fg/jobs/kill, &, dirstack pushd/popd/dirs |
โ |
| Builtins | getopts, read, printf, alias/unalias, hash, type, local, โฆ |
โ |
| Arrays | indexed a=(โฆ), a[i]=v, ${a[i]}, ${a[@]}, declare -a |
๐ง (Wk2โ3) |
set -e |
abort on failure in a multi-stage pipeline (simple commands โ ) | ๐ง (Wk3) |
| Assoc. arrays | declare -A, string keys |
๐ |
| Pattern/misc | ${v/pat/repl}, var+=value (string append), extglob, [[ str == glob ]] RHS, mapfile/namerefs/coproc |
๐ |
Honesty matters more than a green wall: the ๐ง/๐ rows are real gaps, tracked openly. The โ rows are each locked behind a regression test that's diffed against
bash --posix.
Arrays โ the headline of this cycle ๐ง¶
Arrays are the single biggest compatibility unlock (a huge fraction of real bash scripts use them), and they're the current focus.
# Target syntax (Weeks 2โ3)
declare -a fruits=(apple banana cherry)
fruits[3]=date
echo "${fruits[@]}" # apple banana cherry date
echo "${#fruits[@]}" # 4
echo "${!fruits[@]}" # 0 1 2 3
fruits+=(elderberry) # append
for f in "${fruits[@]}"; do echo "$f"; done # one field per element, even quoted
Why it's a real change, not a bolt-on: hellish's variable store is currently one string per name.
Arrays add a value-vector + type tag to that store, subscript parsing on the assignment side, and
@/* handling (with the subtle ""${a[@]}" splits to one field per element even when quoted"
rule) on the expansion side โ plus a declare/typeset builtin. The good news: bash arrays are
shell-local (never exported to the environment), so the execve path is untouched.
How compatibility is guaranteed¶
Every fixed construct gets a permanent regression case, and a conformance gate diffs each
construct under hellish vs. bash --posix:
make -C vendor/42sh test # the full suite (2481+ cases, growing)
HELLISH=โฆ bash scripts/conformance.sh # construct-by-construct vs bash โ 0 divergences
If a behavior diverges from bash, it shows up here before it ships. That's the contract behind every โ above.
See also: Interactive Experience ยท Performance & Robustness ยท What hellish is + Install