Linux Basic — Builtins vs External

1 minute read

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

Updated: