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
~/.bashrcand~/.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