Difference between sh and Bash

Learn difference between sh and bash with practical examples, diagrams, and best practices. Covers bash, shell, unix development techniques with visual explanations.

sh vs. Bash: Understanding the Core Differences in Unix Shells

Hero image for Difference between sh and Bash

Explore the fundamental distinctions between the traditional 'sh' shell and the widely used 'Bash' (Bourne Again SHell), including features, compatibility, and practical implications for scripting and command-line usage.

In the world of Unix-like operating systems, the shell is your primary interface for interacting with the kernel. It's a command-line interpreter that executes commands and scripts. Two of the most common shells you'll encounter are sh (Bourne Shell) and Bash (Bourne Again SHell). While Bash is often the default shell on many modern Linux distributions, sh holds historical significance and remains crucial for POSIX compliance and basic scripting. Understanding their differences is vital for writing portable scripts and effectively managing your system.

The Legacy of sh: The Bourne Shell

sh, or the Bourne Shell, was developed by Stephen Bourne at Bell Labs and released in 1979. It was the first widely available Unix shell and became the standard for Unix systems. Its primary goal was to provide a simple, efficient, and powerful command interpreter and scripting language. sh is known for its minimalist design and adherence to the POSIX standard, which defines a set of standards for maintaining compatibility between operating systems. This makes sh scripts highly portable across different Unix-like systems.

#!/bin/sh

echo "Hello from sh!"

# Basic variable assignment and expansion
my_var="World"
echo "Hello, $my_var!"

# Simple conditional statement
if [ -f "/etc/passwd" ]; then
  echo "/etc/passwd exists."
fi

A simple 'sh' script demonstrating basic commands and syntax.

Bash: The Modern, Feature-Rich Successor

Bash, or the Bourne Again SHell, was created by Brian Fox for the GNU Project as a free software replacement for the Bourne Shell. Released in 1989, Bash is largely compatible with sh but extends its functionality with numerous enhancements. It incorporates features from other popular shells like csh (C Shell) and ksh (Korn Shell), making it a powerful and user-friendly choice for interactive use and complex scripting. Bash is the default interactive shell on most Linux systems and macOS (up to Catalina).

flowchart TD
    A[User Input] --> B{Shell Type?}
    B -->|sh| C[Basic Features]
    B -->|Bash| D[Advanced Features]
    C --> E[POSIX Compliant]
    D --> E
    D --> F[Interactive Enhancements]
    D --> G[Extended Scripting]
    E --> H[Portable Scripts]
    F --> I[History, Aliases, Job Control]
    G --> J[Arrays, Regex, Process Substitution]
    H --> K[Minimal Dependencies]
    I --> L[Improved User Experience]
    J --> M[Complex Automation]

Conceptual flow illustrating the feature sets of sh and Bash.

Key Differences and Practical Implications

While Bash is largely a superset of sh, several key differences impact how you write scripts and interact with the command line. Understanding these distinctions helps in choosing the right shell for a task and ensuring script portability.

1. Feature Set

Bash offers a richer set of features compared to sh. This includes advanced array handling, regular expression matching operators ([[ ... ]] with =~), process substitution (<(command)), enhanced command history, job control, and programmable completion. sh, by contrast, provides a more fundamental set of tools.

2. Interactive Use

For interactive command-line use, Bash is generally preferred due to features like command history recall (up/down arrows), tab completion for commands and filenames, aliases, and customizable prompts. sh typically offers a much more basic interactive experience.

3. Scripting Compatibility and Portability

Scripts written for sh are generally compatible with Bash because Bash aims for sh compatibility. However, Bash-specific features will not run in a pure sh environment. For maximum portability, especially in system startup scripts or embedded systems, sh is often the preferred choice. The shebang line #!/bin/sh explicitly tells the system to execute the script using the sh interpreter, which might be a symlink to dash (Debian Almquist Shell) on some Linux systems, a very lightweight and POSIX-compliant shell.

4. Syntax Extensions

Bash introduces several syntax extensions. For example, [[ ... ]] is a more powerful conditional construct than [ ... ] (test command) used in sh, supporting pattern matching and logical operators like && and || directly. Bash also has different behavior for certain built-in commands and variable expansions.

#!/bin/bash

echo "Hello from Bash!"

# Bash-specific features:

# Array handling
my_array=("apple" "banana" "cherry")
echo "First element: ${my_array[0]}"

# Regular expression matching
if [[ "hello world" =~ "world" ]]; then
  echo "'world' found in string."
fi

# Process substitution
comm -13 <(sort file1.txt) <(sort file2.txt)

# Brace expansion
echo {a..c}.txt

A 'Bash' script showcasing features not available in standard 'sh'.

When to Use Which Shell

Choosing between sh and Bash depends largely on your requirements:

  • Use sh for:

    • System startup scripts (init.d, rc.d) where minimal dependencies and maximum portability are critical.
    • Scripts intended for embedded systems or environments with limited resources.
    • Scripts that must adhere strictly to the POSIX standard.
    • When you need to ensure your script runs on any Unix-like system, regardless of the default shell.
  • Use Bash for:

    • Interactive command-line use on modern Linux/macOS systems.
    • Complex scripts that benefit from advanced features like arrays, associative arrays, regular expressions, and process substitution.
    • Scripts where performance is less critical than development speed and feature availability.
    • When you are certain the target environment has Bash installed and available.
graph TD
    A[Script Requirement] --> B{Portability/POSIX?}
    B -->|Yes| C[Use sh]
    B -->|No| D{Advanced Features/Interactive?}
    D -->|Yes| E[Use Bash]
    D -->|No| C

Decision tree for choosing between sh and Bash for scripting.