Bash
The GNU Project's shell and command language that became the default Unix/Linux shell, powering system administration and automation worldwide.
Created by Brian Fox
Bash (Bourne Again SHell) is both a command-line interpreter and a scripting language that has become the lingua franca of Unix and Linux system administration. Born in 1989 as the GNU Project’s free replacement for the original Bourne shell, Bash combined the best features of its contemporaries—the Bourne shell, the C shell, and the Korn shell—into a single, powerful, and freely distributable package. Today it ships as the default shell on most Linux distributions and remains available on macOS, making it one of the most widely deployed programming environments in the world.
History & Origins
The Bourne Shell Problem
To understand Bash, you must first understand what it replaced. The Bourne shell (sh), written by Stephen Bourne at Bell Labs and released with Unix Version 7 in 1979, was the foundational Unix shell. It was well-designed but proprietary—part of AT&T’s Unix, not freely distributable. In the early 1980s, the GNU Project, founded by Richard Stallman, aimed to create a completely free Unix-compatible operating system. A free shell was essential to that mission.
Brian Fox and the GNU Shell
In January 1988, Richard Stallman commissioned Brian Fox to write a free shell compatible with the Bourne shell but including features from the Korn shell (ksh) and C shell (csh). Fox began development and released the first public version of Bash—version 0.99—on June 8, 1989. The name “Bourne Again SHell” was a pun combining the name of the shell it replaced with the idea of being “born again.”
Bash incorporated:
- Bourne shell compatibility: Scripts written for
shwould largely run unchanged - C shell conveniences: Command history,
!history expansion, aliases - Korn shell features: Command-line editing, job control, functions, arrays
Chet Ramey Takes the Reins
Brian Fox’s involvement with Bash was relatively brief. Chet Ramey, then a student at Case Western Reserve University, had been contributing bug fixes since the early days. In 1990, Ramey became the primary maintainer of Bash—a role he has held continuously for over three decades. This extraordinary continuity of stewardship has been a key factor in Bash’s stability and consistent development.
Design Philosophy
Bash follows the Unix philosophy of doing one thing well, but its “one thing” is broad: providing an interactive interface to the operating system and a scripting language powerful enough to automate complex workflows. Several principles guide its design:
- POSIX Compliance: Bash conforms to the POSIX.1 standard for shell behavior, ensuring portability across Unix-like systems
- Backward Compatibility: Scripts written for older versions of Bash should continue to work; breaking changes are avoided
- Interactive Usability: Features like readline integration, command completion, and history make interactive use comfortable
- Incremental Complexity: Simple tasks are simple; complex tasks are possible
Key Features
Variables and Parameter Expansion
Bash variables are untyped by default—everything is a string. Parameter expansion provides powerful string manipulation:
| |
Arrays
Bash supports both indexed and associative (hash) arrays:
| |
Control Flow
| |
Functions
| |
Pipeline and Redirection
The pipeline is Bash’s most powerful feature—connecting programs so output of one becomes input of the next:
| |
Here Documents and Here Strings
| |
Arithmetic
| |
Pattern Matching and Globbing
| |
Job Control
Bash provides job control for managing multiple processes:
| |
Bash vs. Other Shells
| Feature | Bash | Zsh | Fish | POSIX sh |
|---|---|---|---|---|
| First Released | 1989 | 1990 | 2005 | 1992 (standardized) |
| Default on Linux | Yes (most distros) | Varies | No | Used in scripts |
| Default on macOS | ≤10.14 | 10.15+ | No | Available |
| Associative Arrays | Bash 4.0+ | Yes | Yes (dicts) | No |
| Regex Matching | =~ | =~ | Built-in | No |
| True/False | 0=success | 0=success | Better | 0=success |
| Config File | .bashrc/.bash_profile | .zshrc | config.fish | .profile |
| Script Compatibility | POSIX mostly | POSIX mostly | Not POSIX | POSIX strict |
The Shellshock Vulnerability
In September 2014, security researcher Stéphane Chazelas discovered CVE-2014-6271, known as “Shellshock”—one of the most severe vulnerabilities in Bash’s history. The flaw involved how Bash processed function definitions passed through environment variables. An attacker could append arbitrary commands after a function definition, and Bash would execute them when invoked:
| |
Because many web servers (via CGI) and network services invoked Bash with user-controlled environment variables, this created a remote code execution path. Patches were released within days, but the incident highlighted the risks of Bash being invoked by network-facing services. The vulnerability affected Bash versions from at least 1.14 through 4.3.
Scripting Best Practices
Experienced Bash programmers follow conventions that make scripts more robust:
| |
ShellCheck: The Linter
ShellCheck is an open-source static analysis tool for shell scripts that catches common mistakes, POSIX incompatibilities, and style issues. It has become an essential part of modern Bash development, often integrated into CI/CD pipelines:
| |
Evolution
Bash 4.0 (2009): Associative Arrays and Coproc
The addition of associative arrays in Bash 4.0 was transformative for scripting complex data:
| |
Coprocesses allowed two-way communication with a background process:
| |
Bash 5.0 (2019): New Variables and Improvements
Bash 5.0 introduced EPOCHSECONDS (seconds since the Unix epoch) and EPOCHREALTIME (with microsecond precision) as convenient built-in variables, eliminating the need to call external utilities for timestamp operations in time-sensitive scripts.
Bash 5.2 (2022)
Bash 5.2 refined behavior around string transformations, fixed edge cases in word splitting and glob expansion, and improved the behavior of local variables in recursive function calls.
Current Relevance
Bash’s relevance in 2026 is undeniable: it is the scripting language of Linux infrastructure. While Python has become preferred for complex automation, Bash remains the first choice for:
- System startup and init scripts: systemd unit files frequently call Bash scripts
- Container orchestration: Kubernetes liveness/readiness probes, Docker entrypoints
- CI/CD pipelines: Every major platform (GitHub Actions, GitLab CI, CircleCI) runs Bash by default
- Cloud provisioning: AWS user data scripts, Azure custom script extensions, GCP startup scripts
- Developer tooling:
./configurescripts,Makefilerecipes, install scripts
The shell scripting ecosystem around Bash—ShellCheck for linting, bats (Bash Automated Testing System) for testing, and shellspec for BDD-style tests—reflects a mature, professional toolchain.
Why Bash Matters
Bash occupies a unique position in computing history: it is both old infrastructure and modern necessity. Created as part of the GNU Project’s mission to create free software, it became the default shell of the Linux operating system—which became the default operating system of the internet. Every major cloud provider, every container runtime, every CI/CD system depends on Bash.
Its influence extends beyond direct use. Fish and Dash define themselves partly in relation to Bash—either improving on it or optimizing for specific use cases. PowerShell, Microsoft’s modern shell for Windows, reportedly drew inspiration from the Unix shell tradition’s pipeline and scripting concepts, though it was designed independently with a distinct object-oriented model.
For any developer working with Unix-like systems, Bash is not optional knowledge—it is foundational. Understanding Bash means understanding how Unix systems are administered, how software is built, and how infrastructure is automated at scale.
Timeline
Notable Uses & Legacy
Linux System Administration
Bash is the default login shell on most Linux distributions and is universally used for system startup scripts (init/systemd), cron jobs, and administrative automation.
CI/CD Pipelines
GitHub Actions, GitLab CI, Jenkins, and virtually every CI/CD platform use Bash as the default scripting language for build, test, and deployment steps.
macOS
Bash was the default interactive shell on macOS from its early releases through 10.14 (Mojave, 2018); Apple switched the default to Zsh in macOS 10.15 (Catalina, 2019), though Bash 3.2 remains available for compatibility.
Docker and Container Tooling
Docker's official entrypoint scripts, Kubernetes health check probes, and the vast majority of container initialization scripts are written in Bash.
Infrastructure Automation
Ansible uses Bash as the default execution shell on managed nodes; Terraform provisioners and cloud-init scripts commonly use Bash for instance bootstrapping.
Open Source Build Systems
Autoconf-generated configure scripts, GNU Makefile rules, and the build systems for countless open source projects including the Linux kernel's kbuild system use Bash scripts extensively.
Language Influence
Influenced By
Influenced
Running Today
Run examples using the official Docker image:
docker pull bash:5.2Example usage:
docker run --rm -v $(pwd):/app -w /app bash:5.2 bash hello.sh