Andrew Mercer

Let me check coreutils first.The authoritative list straight from the GitHub source is: [ arch b2sum base32 base64 basename basenc cat chcon chgrp chmod chown chroot cksum comm coreutils cp csplit cut date dd df dir dircolors dirname du echo env expand expr factor false fmt fold groups head hostid hostname id install join kill link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup nproc numfmt od paste pathchk pinky pr printenv printf ptx pwd readlink realpath rm rmdir runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred shuf sleep sort split stat stdbuf stty sum sync tac tail tee test timeout touch tr true truncate tsort tty uname unexpand uniq unlink uptime users vdir wc who whoami yes

My previous list was missing arch, hostname, tsort, and runcon, and incorrectly included chcon and basenc which are actually present. Here's the corrected mkdir:

mkdir -p coreutils/{arch,b2sum,base32,base64,basename,basenc,cat,chcon,chgrp,chmod,chown,chroot,cksum,comm,cp,csplit,cut,date,dd,df,dir,dircolors,dirname,du,echo,env,expand,expr,factor,false,fmt,fold,groups,head,hostid,hostname,id,install,join,kill,link,ln,logname,ls,md5sum,mkdir,mkfifo,mknod,mktemp,mv,nice,nl,nohup,nproc,numfmt,od,paste,pathchk,pinky,pr,printenv,printf,ptx,pwd,readlink,realpath,rm,rmdir,runcon,seq,sha1sum,sha224sum,sha256sum,sha384sum,sha512sum,shred,shuf,sleep,sort,split,stat,stdbuf,stty,sum,sync,tac,tail,tee,test,timeout,touch,tr,true,truncate,tsort,tty,uname,unexpand,uniq,unlink,uptime,users,vdir,wc,who,whoami,yes}

Now, bash and bash builtins:

Bash

Bash (Bourne Again SHell) was written by Brian Fox for the GNU Project in 1989 as a free replacement for the Bourne shell (sh). It is now maintained by Chet Ramey at Case Western Reserve University, who has been the primary maintainer since 1990. It is the default login shell on most Linux distributions and was the default on macOS until Catalina replaced it with zsh in 2019.

Bash is simultaneously four things: a command interpreter, a scripting language, a job controller, and a readline-based interactive environment. Understanding which hat it's wearing at any given moment is key to understanding its sometimes surprising behavior.


Architecture

When you run bash, it goes through distinct phases for every line of input: lexing, parsing, expansion, and execution. The expansion phase alone has seven ordered steps that bash applies before a command ever runs:

  1. Brace expansion — {a,b,c} or {1..10}
  2. Tilde expansion — ~$HOME
  3. Parameter and variable expansion — $VAR, ${VAR}, ${VAR:-default}
  4. Command substitution — $(command) or `command`
  5. Arithmetic expansion — $(( expr ))
  6. Word splitting — split on $IFS
  7. Pathname expansion (globbing) — *, ?, [...]

Order matters enormously — many subtle bugs come from assumptions about which expansion happens first.


Builtins — what they are and why they exist

A builtin is a command implemented inside the bash process itself rather than as a separate executable on disk. Builtins exist for two reasons: either the operation is impossible to implement as an external process (you can't change the shell's working directory from a child process — cd must be a builtin), or the performance cost of forking a child process is prohibitive for something called constantly.

When you type a command, bash looks it up in this order:
1. Aliases
2. Functions
3. Builtins
4. External commands (via $PATH)

You can force the external version of a command with the full path (/bin/echo) or with command echo. You can force the builtin with builtin echo.


Builtins by category

Navigation and environment
- cd — change the current directory (must be a builtin)
- pwd — print working directory (builtin version; /bin/pwd also exists)
- export — mark variables for export to child processes
- unset — unset variables or functions
- set — set shell options or positional parameters
- env — not a builtin (coreutils), but export is the builtin equivalent
- declare / typeset — declare variables with attributes (integer, array, readonly, etc.)
- local — declare local variables inside functions
- readonly — mark variables as read-only
- shift — shift positional parameters left

I/O
- echo — print arguments (builtin version; behavior differs from /bin/echo on -e)
- printf — formatted output (builtin; more portable than echo for complex formatting)
- read — read a line from stdin into variables
- readarray / mapfile — read lines from stdin into an array

Control flow
- if / then / elif / else / fi
- for / while / until / do / done
- case / esac
- select — generate a menu from a list
- break / continue — loop control
- return — return from a function
- exit — exit the shell with a status

Test and evaluation
- test / [ — evaluate conditional expressions (POSIX compatible)
- [[ — extended conditional expression (bash-specific, not POSIX)
- (( )) — arithmetic evaluation
- $[[ ]] — deprecated arithmetic, use (( )) instead
- true / false — return 0 or 1 (also coreutils externals; builtins shadow them)

Job control
- jobs — list active jobs
- fg — bring a job to the foreground
- bg — send a job to the background
- wait — wait for a job or process to finish
- kill — send a signal (builtin version; util-linux and coreutils versions also exist)
- disown — remove a job from the job table
- suspend — suspend the shell

Functions and sourcing
- source / . — execute a script in the current shell context (must be a builtin)
- function — define a function (keyword, not strictly a builtin)
- unset — remove a function or variable
- return — return a value from a function

History
- history — display or manipulate the command history
- fc — fix command — edit and re-execute history entries
- bind — bind a readline key sequence to a function

Shell introspection
- type — describe how a name would be interpreted (alias, function, builtin, file)
- command — find or run a command, bypassing aliases and functions
- builtin — run a shell builtin explicitly
- enable — enable or disable shell builtins
- help — display help for builtins
- caller — return the context of a subroutine call (useful for stack traces)
- hash — remember or report full pathnames of commands

Options and debugging
- set -e — exit on error
- set -u — treat unset variables as errors
- set -x — print commands as they execute (debug trace)
- set -o pipefail — catch failures in pipelines
- shopt — set/unset bash-specific shell options (different from set)
- trap — set signal handlers or cleanup functions
- times — print accumulated user and system times

Misc
- alias / unalias — define and remove aliases
- getopts — parse option arguments in scripts
- eval — evaluate a string as a shell command (use carefully)
- exec — replace the shell with a command (or redirect shell file descriptors)
- ulimit — set or display resource limits
- umask — set the file creation mask
- xargs — not a builtin (findutils)
- compgen / complete / compopt — programmable completion system


Key behavioral distinctions

[ vs [[[ is a POSIX builtin that also exists as /bin/[ (yes, really). [[ is bash-only and handles more cases safely — unquoted variables don't word-split inside [[, regex matching with =~ is supported, and &&/|| work directly instead of needing -a/-o. In bash scripts targeting only bash, prefer [[. In scripts targeting /bin/sh or dash, use [.

echo portabilityecho -e to interpret escape sequences is bash-specific behavior. Dash's echo ignores -e. POSIX does not define -e at all. printf is the portable alternative and should be preferred in any script meant to run on sh.

source vs . — identical in bash. . is the POSIX form and works in sh. source is bash/zsh only.

declare vs locallocal is strictly for function-scoped variables. declare inside a function is equivalent to local but also works at the global scope and supports type attributes like -i (integer), -a (indexed array), -A (associative array), -r (readonly), -x (export).

(( )) vs $(( ))(( expr )) is a command that returns exit status 0 if the arithmetic result is non-zero (useful in if and while). $(( expr )) is an expansion that substitutes the numeric result into the command line.


Startup files and execution modes

Bash behavior changes depending on how it's invoked, which explains a large class of "works in my terminal but not in my script" bugs:

Mode Files sourced
Interactive login shell /etc/profile, then first of ~/.bash_profile, ~/.bash_login, ~/.profile
Interactive non-login shell /etc/bash.bashrc, ~/.bashrc
Non-interactive (script) Only $BASH_ENV if set
sh compatibility mode ~/.profile for login, nothing for non-login

The practical consequence: things you put in ~/.bashrc are not available in cron jobs or scripts run with bash script.sh unless you explicitly source them.


Versioning

Current stable is 5.2 (released 2022). Check with bash --version. Most distributions ship 5.x; macOS ships 3.2 due to the GPL v3 license change in bash 4.0 (Apple hasn't updated it in over 15 years, which is why brew install bash is a common first step on Mac).

Notable version milestones:
- 4.0 — associative arrays (declare -A), mapfile/readarray
- 4.2printf -v to assign to a variable, lastpipe option
- 4.3declare -n nameref variables
- 4.4${parameter@operator} transformations
- 5.0$EPOCHSECONDS, $EPOCHREALTIME, improved globbing
- 5.1${array@K} key/value output, wait -p
- 5.2SRANDOM, BASH_LOADABLES_PATH improvements


Documentation sources

Primary
- The bash man page is exceptionally comprehensive — man bash is one of the longest and most detailed man pages in existence, covering every feature exhaustively
- GNU bash manual (Texinfo): https://www.gnu.org/software/bash/manual/
- Available as single HTML, PDF, or info bash locally
- Source repository: https://git.savannah.gnu.org/cgit/bash.git
- Release tarballs and changelogs: https://ftp.gnu.org/gnu/bash/

Chet Ramey's pages — the maintainer's own resources:
- https://tiswww.case.edu/php/chet/bash/bashtop.html — links to current source, docs, and the bash FAQ
- The bash FAQ maintained by Chet and the community: https://mywiki.wooledge.org/BashFAQ

Community references — these are genuinely excellent and often more practical than the official manual:
- Wooledge wiki (Greg's wiki): https://mywiki.wooledge.org/BashGuide — the most respected community bash guide, covers pitfalls and best practices in depth
- Wooledge pitfalls page: https://mywiki.wooledge.org/BashPitfalls — a catalog of common mistakes with explanations
- Advanced Bash Scripting Guide (ABS): https://tldp.org/LDP/abs/html/ — very comprehensive, though some examples show older style; treat as reference not gospel
- shellcheck.net — paste any bash script and get annotated warnings; also available as a local tool (shellcheck)

Builtins specifically

help              # list all builtins
help cd           # help for a specific builtin
help set          # covers all set options
help shopt        # covers all shopt options

The help builtin is the fastest reference for builtin-specific syntax — faster than man bash when you just need to check a flag.

Books
- Learning the bash Shell by Cameron Newham — O'Reilly, good introductory reference
- bash Cookbook by Carl Albing and JP Vossen — O'Reilly, practical recipes
- The Linux Command Line by William Shotts — freely available at https://linuxcommand.org/tlcl.php, covers bash thoroughly in a practical context

Portability and POSIX
- https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html — POSIX shell grammar and builtins specification, the definitive reference for what's portable vs bash-specific
- dash source code and man page — reading what dash implements vs what bash adds is a fast way to understand the POSIX/bash divide