Linux Basic — Builtins vs External
Builtins vs External
Bash builtins run inside the shell — no fork. External commands (/bin/grep, /usr/bin/awk) fork every time.
Check if a Command is a Builtin
type -a cd
# cd is a shell builtin
type -a grep
# grep is /usr/bin/grep
Common Builtins to Prefer
| External | Builtin | Speedup |
|---|---|---|
test / [ |
[[ |
10× in loops |
expr |
$(( )) |
50× |
seq |
{1..N} |
5× |
basename |
${var##*/} |
10× |
dirname |
${var%/*} |
10× |
echo |
printf (sometimes) |
marginal |
[[ vs [ / test
# SLOW — forks /usr/bin/test
if [ "$x" = "y" ]; then
# FAST — builtin
if [[ "$x" == "y" ]]; then
[[ also supports regex (=~), glob matching, and logical ops (&&, ||) without escaping.
Arithmetic: $(( )) vs expr
# SLOW — fork
result=$(expr $a + $b)
# FAST — builtin
result=$((a + b))
String Manipulation
file="/path/to/file.txt"
# SLOW — fork basename
name=$(basename "$file")
# FAST — parameter expansion
name=${file##*/}
# SLOW — fork dirname
dir=$(dirname "$file")
# FAST
dir=${file%/*}
Loops: {1..N} vs seq
# SLOW — forks seq
for i in $(seq 1 1000); do
# FAST — brace expansion (Bash 3+)
for i in {1..1000}; do
Caveat: {1..N} doesn’t support variables in Bash < 4. Use seq if you need dynamic ranges in old Bash.
When External Tools Are Still Right
| Task | Prefer | Why |
|---|---|---|
| Pattern matching in files | grep |
optimised C code, handles large files |
| Text transformation | sed / awk |
domain-specific, faster than Bash loops |
| Sorting | sort |
external merge-sort beats Bash arrays |
| Deduplication | uniq |
fast, standard |
Use builtins for glue code; use external tools for heavy lifting.
Benchmark Example
# external (10k iterations): ~8 seconds
time for i in {1..10000}; do
test "$i" -gt 5000
done
# builtin: ~0.2 seconds
time for i in {1..10000}; do
[[ $i -gt 5000 ]]
done
40× speedup just by using [[.
Next → Array vs String Performance