The column utility takes messy, unaligned text and arranges it into
neat columns. Feed it a list or delimited data and it calculates optimal widths
automatically — no manual field-width arithmetic needed. It is the fastest way
to turn raw command output into something readable at a glance.
Two main modes: table mode
(-t) takes delimited input and aligns it into columns, and
fill mode arranges items to fit the terminal width.
The util-linux version (standard on RHEL/Ubuntu) has additional flags
for headers, separators, and right-alignment.
The most common use — take whitespace-separated data and align it:
# Without column — hard to read echo "NAME STATUS PID MEMORY nginx running 1234 45MB sshd running 891 12MB postgresql running 2201 380MB redis stopped - -" | cat # With column -t — instant alignment echo "NAME STATUS PID MEMORY nginx running 1234 45MB sshd running 891 12MB postgresql running 2201 380MB redis stopped - -" | column -tWithout column:
column -t instantly makes it readable. No format strings,
no field widths — column calculates everything from the data.
Process colon-delimited, CSV, or tab-separated data:
# Format /etc/passwd nicely cut -d: -f1,3,6,7 /etc/passwd | column -t -s ':' # Format a CSV (simple — no quoted fields) echo "hostname,ip,role,os web01,192.168.1.10,nginx,Ubuntu22 db01,192.168.1.20,postgresql,RHEL9 cache01,192.168.1.30,redis,Ubuntu22" | column -t -s ',' # Tab-delimited — from a script or spreadsheet export printf "Server\tCPU\tRAM\tDisk\n" > /tmp/inv.tsv printf "web01\t4\t16GB\t500GB\n" >> /tmp/inv.tsv printf "db01\t16\t64GB\t2TB\n" >> /tmp/inv.tsv column -t -s $'\t' /tmp/inv.tsvCSV output:
$'\t' (ANSI-C quoting) to pass
a literal tab to -s. Plain "\t" in double quotes
does not expand to a tab in all shells.
Inject a header row without it being in the data stream:
# Add headers to ps output ps aux --no-headers | awk '{print $1,$2,$3,$11}' | \ column -t -N "USER,PID,CPU%,COMMAND" # Add headers to a data file that has none column -t -s ',' -N "HOST,IP,ROLE,OS" /tmp/servers.csv # Right-align numeric columns with -R (util-linux 2.32+) echo "server cpu mem disk web01 4 16 500 db01 16 64 2000 cache01 2 8 100" | column -t -R 2,3,4With headers and right-aligned numbers:
-N and -R flags
require util-linux 2.30+ and 2.32+ respectively. Check your version with
column --version. Older systems (RHEL 7, Ubuntu 18.04) may not
have these flags — use printf for headers on older systems.
Without -t, column fills the terminal width with items
arranged in columns — like ls does:
# List items across terminal width ls /etc | column # Force a specific width ls /etc | column -c 60 # Display a list of packages in columns rpm -qa --queryformat "%{NAME}\n" | sort | column # Show available bash builtins in columns compgen -b | columncompgen -b | column output:
-x to fill across then down — like reading order.
Pipe common commands through column for instant readability:
# Mount points — cleaner than raw mount output mount | grep -v "cgroup\|proc\|sys\|dev\|run" | \ awk '{print $1, $3, $5}' | column -t # Environment variables as a table env | sort | column -t -s '=' # Listening ports — cleaner ss output ss -tlnp | column -t # /etc/hosts as aligned table grep -v "^#\|^$" /etc/hosts | column -t # crontab entries aligned crontab -l | grep -v "^#" | column -t/etc/hosts example:
#!/bin/bash # Server inventory report using column TMPFILE=$(mktemp) trap 'rm -f "$TMPFILE"' EXIT # Build data into temp file — header first echo "HOSTNAME IP_ADDRESS CPU_CORES RAM_GB DISK_GB OS_VERSION" > "$TMPFILE" echo "-------- ---------- --------- ------ ------- ----------" >> "$TMPFILE" for host in web01 web02 db01 cache01; do # In real life these would be ssh calls printf "%s %s %s %s %s %s\n" \ "$host" \ "192.168.1.$(shuf -i 10-50 -n1)" \ "$(shuf -i 2-16 -n1)" \ "$(shuf -i 4-64 -n1)" \ "$(shuf -i 100-2000 -n1)" \ "RHEL9" >> "$TMPFILE" done # Format and display echo "" echo "=== Server Inventory ===" echo "" column -t "$TMPFILE" echo ""Output:
# column — best when data width is unknown at script write time # Let column figure out widths from actual data getent passwd | cut -d: -f1,3,7 | column -t -s ':' # printf — best when you control the format and need exact widths printf "%-20s %6s %s\n" "USERNAME" "UID" "SHELL" printf "%-20s %6s %s\n" "--------" "---" "-----" while IFS=: read -r user _ uid _ _ _ shell; do printf "%-20s %6s %s\n" "$user" "$uid" "$shell" done < /etc/passwd # Combine both — printf for header, column for data printf "%-s\t%-s\t%-s\n" "USER" "UID" "SHELL" printf "%-s\t%-s\t%-s\n" "----" "---" "-----" cut -d: -f1,3,7 /etc/passwd | column -t -s ':'
column -t.
If you know the widths ahead of time and need precise control (reports with
fixed-width numeric fields), use printf. They work beautifully
together.
Combining column with printf for polished bordered output:
#!/bin/bash # Disk usage table with separator SEP=$(printf '%0.s-' {1..55}) { echo "FILESYSTEM TOTAL USED AVAIL USE%" echo "$SEP" df -h --output=target,size,used,avail,pcent | \ tail -n +2 | \ grep -v "tmpfs\|udev" } | column -t # Hidden trick — use column on its own --table-* options (util-linux 2.30+) # to add column separators echo "NAME AGE CITY Alice 34 Albany Bob 28 Binghamton Craig 65 Vestal" | column -t --table-columns NAME,AGE,CITY \ --table-right AGEDisk usage output:
| Command | What it does |
|---|---|
| cmd | column -t | Auto-align whitespace-delimited output into columns |
| cmd | column -t -s ':' | Use colon as field delimiter |
| cmd | column -t -s ',' | Use comma as delimiter (simple CSV) |
| cmd | column -t -s $'\t' | Tab-delimited input |
| cmd | column -t -N "H1,H2" | Add header row (util-linux 2.30+) |
| cmd | column -t -R 2,3 | Right-align columns 2 and 3 (util-linux 2.32+) |
| cmd | column | Fill mode — arrange items across terminal width |
| cmd | column -c 80 | Fill mode — wrap to 80 columns |
| cmd | column -x | Fill across then down (reading order) |
| column -t file.txt | Read from file instead of stdin |
| column --version | Check util-linux version for feature availability |
| Situation | Tool | Why |
|---|---|---|
| Variable-length data (names, paths) | column -t | Calculates widths from data automatically |
| Fixed numeric fields, precise alignment | printf | You control exact field widths |
| Quick pipe to clean up command output | column -t | One flag, no format string needed |
| Colon/CSV/tab delimited input | column -t -s | Built-in delimiter support |
| ANSI colors, special formatting | printf | column strips/misaligns with escape codes |
| Headers on data without headers | column -N | Inject header without touching data |
printf when color and alignment are both needed.