The shell
Computerwelt.Emulation.Bash is a bash interpreter written in C#: a lexer, a recursive-descent
parser with its own fuel budget, and an evaluator, plus the command implementations a script
expects to find.
var bash = Bash.CreateBuilder()
.WithWorkingDirectory("/home/agent")
.WithUsername("agent")
.WithHostname("sandbox")
.WithEnvironmentVariable("LANG", "C.UTF-8")
.WithLimits(ExecutionLimits.Strict)
.Build();
The session keeps state between ExecAsync calls the way a terminal does: the working directory,
exported variables, shell functions, aliases and history all persist.
Language support
Everything a script written against POSIX bash normally uses:
| Expansion | parameter, brace, tilde, arithmetic, command substitution, process substitution, globbing |
| Quoting | single, double, $'…', heredocs and here-strings |
| Redirection | >, >>, <, 2>, &>, >&, file descriptors, pipes |
| Control flow | if, for, while, until, case, select, &&, \|\|, ! |
| Functions | definition, arguments, local, return, recursion up to the depth limit |
| Variables | scalars, arrays, associative arrays, ${…} modifiers, declare / readonly / export |
| Arithmetic | $(( … )), let, ((…)) |
| Traps and jobs | trap, exit, exit-status semantics |
Exit codes are kept exact, because scripts branch on them: 127 is command not found, 126 is not executable, and 2 is a parse or usage error.
Commands
Over a hundred commands ship, all managed implementations:
| Group | Commands |
|---|---|
| Navigation and files | cd, pwd, ls, tree, stat, file, mkdir, rmdir, rm, cp, mv, ln, touch, chmod, chgrp, truncate, mktemp, readlink, realpath, basename, dirname, du, df |
| Reading and writing | cat, head, tail, tac, rev, nl, tee, wc, od, xxd, strings, column, paste |
| Searching | grep / egrep / fgrep, rg, find, which, type |
| Transforming | sed, awk / gawk / mawk, cut, tr, sort, uniq, comm, shuf, seq, numfmt, printf, echo, diff |
| Structured data | jq, yq |
| Archives and checksums | tar, md5sum, sha1sum, sha256sum and friends |
| Shell builtins | export, local, readonly, unset, set, shopt, alias, unalias, eval, exec, source, ., read, readarray / mapfile, getopts, shift, trap, test / [, true, false, :, let, expr, bc |
| Process-shaped | xargs, timeout, sleep, wait, kill, jobs, command, hash, history, dirs, pushd, popd |
| Environment | env, printenv, date, id, whoami, hostname, uname, compgen |
Bash.BuiltinNames enumerates what a given session actually has, which is the authoritative answer
after registrations and withholdings are applied.
Process-shaped, not process-backed
kill, jobs and timeout behave the way a script expects, but there are no operating-system
processes underneath them. sleep consumes the wall-clock budget like anything else.
Read next
- Extending the shell — adding commands, and taking them away.
- Python — the other half.
- Limits — what bounds a script.