DEV Community

Solomon
Solomon

Posted on

Your Shell Colon Does Nothing — Use It Anyway

Your shell colon does nothing. It literally does nothing. And yet, seasoned Unix users reach for it constantly — for loops, variable assignments, file truncation, and placeholder logic. If you've ever wondered why : appears in shell scripts for reasons that seem absurd, this article is for you. By the end, you'll see : as one of the most underrated tools in your scripting arsenal.

What the Colon Actually Does

In POSIX shells (bash, dash, zsh, sh), the colon (:) is a built-in command that does nothing and exits with a status code of zero. It's a no-op — a null command that consumes no resources and produces no output.

:
Enter fullscreen mode Exit fullscreen mode

That's it. Run it. Nothing happens. Your shell just moves on to whatever comes next.

Under the hood, the colon is defined by POSIX as:

The colon utility shall do nothing beyond expanding arguments and performing specified redirections. The exit status shall be zero.

So why use something that does absolutely nothing? Because in shell scripting, doing nothing is a superpower.

The : as a True Substitute for true

Many scripts use true to represent a successful, always-passing condition. But true is an external binary on some systems — /usr/bin/true — which means your shell has to fork a process to execute it. The colon is a shell built-in, so it runs instantly without any process overhead.

# Both evaluate to true, but : is faster
if true; then
  echo "This works"
fi

if :; then
  echo "This works too — and faster"
fi
Enter fullscreen mode Exit fullscreen mode

In a script that runs thousands of condition checks, that difference adds up. When you're writing performance-sensitive shell code, : is the leaner choice.

Infinite Loops with while :

One of the most common uses of the colon is in infinite loops. You'll see this pattern everywhere in daemon scripts, health checks, and retry logic:

while :; do
  echo "Running..."
  sleep 5
done
Enter fullscreen mode Exit fullscreen mode

This is functionally identical to while true; do ... done, but it avoids spawning an external command. On minimal systems (embedded Linux, containers, Alpine Linux), true might not even exist — but : always does because it's part of the shell itself.

This matters if you're deploying lightweight containers on Cloudflare Workers or building minimal Docker images where every byte counts. Using built-in : instead of external binaries keeps your footprint small.

The Colon as a Default-Value Setter

This is where things get genuinely interesting. The colon has a side effect that most developers don't know about: when used with parameter expansion, it can set default values as a side effect.

# Set DEFAULT_VAR only if MY_VAR is unset or empty
: "${MY_VAR:=default_value}"
echo "$MY_VAR"  # prints "default_value" if MY_VAR was unset
Enter fullscreen mode Exit fullscreen mode

The ${var:=default} syntax assigns the default value to var if it's unset or null. But here's the trick: you can't just write ${MY_VAR:=default_value} by itself in POSIX sh — the shell will throw a syntax error because parameter expansion isn't a complete command on its own. You need something to "consume" it, and : is perfect for that.

This pattern is ubiquitous in shell scripts and you'll see it in configuration loaders, CI/CD pipelines, and startup scripts. It's a compact, idiomatic way to handle defaults.

Compare this with a more verbose alternative:

# Without the colon trick — much more verbose
if [ -z "${MY_VAR}" ]; then
  MY_VAR="default_value"
fi
Enter fullscreen mode Exit fullscreen mode

The one-liner with : is cleaner, faster to type, and harder to mess up.

Truncating Files with : > file

Need to empty a file without deleting it? The colon makes this dead simple:

: > mylogfile.txt
Enter fullscreen mode Exit fullscreen mode

This redirects the "nothing" produced by : into mylogfile.txt, effectively truncating it to zero bytes. It's equivalent to > mylogfile.txt or cat /dev/null > mylogfile.txt, but more explicit and self-documenting once you know what it means.

I use this pattern when I'm rotating log files in deployment scripts, particularly when I'm managing services deployed on Vercel or similar platforms where I need to reset temporary output files between build stages.

Placeholder Commands During Script Development

When you're scaffolding a script and haven't written the logic for a particular branch yet, the colon serves as a perfect placeholder:

case "$ENVIRONMENT" in
  production)
    # TODO: add production deployment logic
    :
    ;;
  staging)
    echo "Deploying to staging..."
    ./deploy-staging.sh
    ;;
  *)
    echo "Unknown environment: $ENVIRONMENT"
    exit 1
    ;;
esac
Enter fullscreen mode Exit fullscreen mode

Unlike leaving an empty block (which can cause syntax errors in some shells), : is a valid command that does nothing and signals to future readers: "this branch is intentionally a no-op for now."

This is especially useful when you're organizing your workflow — I keep a running list of script ideas and TODOs in Notion (check it out at notion.so/signup) so I can revisit these placeholders and fill them in later.

The Colon in Boolean Logic Chains

Shell scripts often chain commands using && (and) and || (or). The colon can act as a reliable anchor point in these chains:

# Run cleanup even if the main command fails
do_something && :
cleanup
Enter fullscreen mode Exit fullscreen mode

Or as a guaranteed starting point in a chain:

# Ensure we start with a known success state
: && step_one && step_two && step_three
Enter fullscreen mode Exit fullscreen mode

These patterns are subtle but powerful. They let you build robust, fault-tolerant scripts without adding complexity.

: vs. true vs. false

Let's quickly compare the three for clarity:

Command Type Exit Code Overhead
: Built-in 0 (success) None
true Built-in or external 0 (success) Depends on system
false Built-in or external 1 (failure) Depends on system

On most modern Linux systems, true and false are also built-ins, so the distinction is mostly academic. But on older Unix systems, BusyBox-based embedded Linux, or minimal container environments, the built-in status of : is a guaranteed constant you can rely on.

Practical Example: A Retry Loop

Here's a real-world example that combines several colon tricks:

#!/bin/sh

MAX_RETRIES=5
RETRY_COUNT=0

while :; do
  echo "Attempt $((RETRY_COUNT + 1))..."

  if curl -sf https://api.example.com/health; then
    echo "Service is healthy!"
    break
  fi

  RETRY_COUNT=$((RETRY_COUNT + 1))

  if [ "$RETRY_COUNT" -ge "$MAX_RETRIES" ]; then
    echo "Max retries reached. Giving up."
    exit 1
  fi

  echo "Waiting 3 seconds before retry..."
  sleep 3
done
Enter fullscreen mode Exit fullscreen mode

Notice the while :; do pattern — it's the standard idiom for "run forever until we break." The script is portable, efficient, and works on any POSIX-compliant shell, from bash to dash to busybox ash.

Why This Matters for Modern DevOps

You might think "who still writes shell scripts in 2025?" But the truth is that shell is everywhere: Docker entrypoint scripts, CI/CD pipeline steps, Kubernetes init containers, GitHub Actions workflows, and infrastructure provisioning hooks.

When you're writing these scripts, every line matters. Using : instead of unnecessary external commands, leveraging parameter expansion tricks, and writing idiomatic shell code means scripts that are faster, more portable, and more maintainable.

I keep my personal shell utilities and dotfiles organized on GitHub (github.com) — having a public repo of well-documented scripts is a great way to build habits around clean, idiomatic shell writing.

TL;DR

The colon in shell scripting is a built-in null command that exits successfully. It does nothing, and that's exactly why it's so useful:

  • while : — create infinite loops without external commands
  • :${VAR:=default} — set default values as a side effect
  • : > file — truncate files cleanly
  • : as placeholder — skip branches during development
  • : in boolean chains — anchor reliable success states

Next time you see a colon in a shell script, don't skip past it. Stop and appreciate that the person who wrote it understood a subtle but powerful tool — and now you do too.


Solomon is a full-stack developer and DevOps enthusiast who writes about practical tooling, automation, and the quiet elegance of Unix. You can find more of his work on Dev.to and Medium.


Enjoyed this? I build simple, powerful AI tools — try the free Text Summarizer or browse the full toolkit at Solomon Tools. No signup, no subscription.

Top comments (0)