In Unix-like systems, /bin/sh
traditionally serves as the system's default shell interpreter. While many Linux distributions historically symlinked /bin/sh
to Bash (/bin/bash
), modern systems often point it to /bin/dash
(Debian Almquist Shell) for performance reasons.
# Check where /bin/sh points: ls -l /bin/sh # Typical output: /bin/sh -> dash
Despite both being shells, dash and bash have significant technical differences:
- POSIX Compliance: dash strictly follows POSIX standards, while bash includes extensions
- Features: bash supports arrays, associative arrays, and advanced pattern matching that dash lacks
- Startup Files: bash reads
~/.bashrc
and~/.bash_profile
, dash only reads~/.profile
- Performance: dash is lighter and faster for system scripts
The $SHELL
variable indicates your login shell, not necessarily your current shell:
# In dash: echo $SHELL # Output: /bin/bash (your login shell) echo $0 # Output: dash (current shell)
When writing shell scripts, you should explicitly declare the interpreter:
#!/bin/bash # For bash-specific features like arrays my_array=(1 2 3) echo ${my_array[1]} #!/bin/sh # For POSIX-compliant scripts echo "This will work in any sh-compatible shell"
Most system init scripts use #!/bin/sh
for portability. Here's a comparison:
# Bash-specific (won't work in dash) if [[ $var == *.txt ]]; then echo "Text file" fi # POSIX-compliant (works in both) case "$var" in *.txt) echo "Text file";; esac
While not recommended, you can change the symlink (with caution):
sudo ln -sf /bin/bash /bin/sh # Verify: ls -l /bin/sh
Remember this might break system scripts expecting dash behavior.
To test if a feature works in dash:
dash -c 'your_command_here' # Example: dash -c 'echo ${BASH_VERSION}' # Output: (empty) - dash doesn't have this variable
Many Linux users get confused when they discover that /bin/sh
isn't pointing to their preferred shell (often bash) but instead links to /bin/dash
. This isn't an error - it's a deliberate design choice in modern Unix-like systems.
The apparent contradiction where echo $SHELL
shows /bin/bash
while running in dash occurs because:
# $SHELL shows your login shell, not current shell
$ dash
$ echo $SHELL
/bin/bash
$ echo $0
dash
Dash (Debian Almquist Shell) became the default /bin/sh
in Debian/Ubuntu systems because:
- It's significantly lighter than bash
- Boots faster (critical for init scripts)
- Implements POSIX standards more strictly
While dash is POSIX-compliant, bash includes many extensions:
# This works in bash but fails in dash
array=(1 2 3)
echo ${array[1]}
# Dash requires:
set -- 1 2 3
echo $2
To properly identify your current shell:
# Method 1: Read /proc
cat /proc/$$/comm
# Method 2: Check $0
echo $0
# Method 3: Use ps
ps -p $$
Use dash for:
- System startup scripts
- Cases where POSIX compliance is required
- Resource-constrained environments
Use bash for:
- Interactive sessions
- Scripts using bash-specific features
- Development environments
To modify the symlink (not recommended for system stability):
sudo ln -sf /bin/bash /bin/sh
# Verify with:
ls -l /bin/sh
Always specify the interpreter explicitly:
#!/bin/bash
# or
#!/bin/dash
For maximum portability, write POSIX-compliant scripts and test with:
dash your_script.sh