for Tabular Output in the Shell
Raw text data separated by commas or tabs becomes hard to read as soon as more than three columns are involved. column -t automatically aligns columns, paste merges several files line by line side by side, and together the two tools build readable reports directly in the shell, without any spreadsheet or external table tool.
Table of contents
- 1. Why readable tabular output in the shell matters
- 2. column -t basics: delimiters and alignment
- 3. paste for merging columns from several files
- 4. Combining column with CSV and TSV
- 5. paste -d for custom delimiters and lines to columns
- 6. Practical example: building a monitoring report from several sources
- 7. Limits with very wide terminals and large datasets
- 8. Alternatives: column -J, pr and printf based formatting
- 9. Comparison: column/paste vs. awk printf for tabular output
- 10. Summary
- 11. FAQ
1. Why readable tabular output in the shell matters
A command like ps aux or a self written CSV analysis often produces technically correct but visually unreadable output: columns of different widths sit next to each other without alignment, which makes it harder to quickly grasp values while debugging or monitoring. This is exactly where tabular output with column and paste comes in, two small but powerful Unix tools that turn raw text data into clearly readable tables.
column solves the problem of column alignment: from a series of delimiter separated values, it builds a table with evenly aligned columns, where every column is brought to the width of its longest entry. paste solves a different but related problem: two or more files get placed side by side line by line, so a shared tabular output emerges from several individual sources, without having to merge the lines manually.
Typical use cases for tabular output with these two tools include monitoring scripts that want to present CPU, memory and disk usage in one combined overview, deployment reports showing the status of several servers side by side, or simple CSV previews right in the terminal, without opening a graphical application for it.
2. column -t basics: delimiters and alignment
The -t option activates the table mode of column and is by far the most commonly used option for tabular output. Without further arguments, column -t recognizes whitespace as the delimiter and aligns all columns so they line up exactly, regardless of how many spaces separated the values in the original. That makes column -t the ideal post processing step for commands like ps, df, or your own scripts that output values separated by irregular spacing.
With the -s option you can define a delimiter other than whitespace, for example -s ',' for comma separated values or -s $'\t' for real tab characters. The -N option in newer column versions additionally allows assigning column names for the header row, which is useful for tabular output tasks where the source file has no header of its own. An important note: column -t loads the entire input into memory before it can compute the maximum column width, which becomes relevant on very large files.
#!/usr/bin/env bash
set -euo pipefail
# Basic table mode: whitespace-separated input, auto-aligned columns
ps aux | column -t
# Custom delimiter: comma-separated values
column -t -s',' sales_export.csv
# Custom delimiter: real tab characters
column -t -s $'\t' export.tsv
# Assign column headers when the source file has none (GNU util-linux 2.36+)
column -t -N "Name,Status,CPU,Memory" -s',' process_snapshot.csv
3. paste for merging columns from several files
While column works within a single file, paste combines several separate files line by line into a shared tabular output. The call paste file_a.txt file_b.txt takes line one from both files, joins them separated by a tab, then line two, and so on, until the longer of the two files is exhausted. For shorter files, paste automatically pads the missing values with an empty field.
This line by line merging is particularly useful when several independent commands each deliver a single column of values, for example a list of hostnames from one file and the corresponding response times from a separate ping run. Instead of manually weaving the values together in a script, paste combines both outputs directly into a tabular output, which can then be further formatted with column -t.
#!/usr/bin/env bash
set -euo pipefail
# Combine two files column-wise, tab-separated by default
paste hostnames.txt response_times.txt
# Chain paste and column -t for an aligned two-column report
paste hostnames.txt response_times.txt | column -t
# Combine three data sources into one report
paste hostnames.txt cpu_usage.txt memory_usage.txt | column -t -N "Host,CPU%,Mem%"
# Serial mode: merge lines from a single file into a single row (-s)
paste -s -d',' single_column_values.txt
4. Combining column with CSV and TSV
For a quick CSV preview right in the terminal, without opening a spreadsheet application, column -t -s',' is the fastest solution for tabular output. This combination reads the CSV file, recognizes the comma as field delimiter, and aligns all values in evenly spaced columns. A common pitfall here: if a column itself contains commas within quotes, as the CSV standard allows, the simple comma splitting of column does not recognize this subtlety and incorrectly splits the field into several columns.
For TSV files with real tab characters as delimiter, the combination column -t -s $'\t' is more reliable, because tabs almost never occur within a single field value and therefore rarely cause misinterpretation. Anyone who regularly needs to prepare CSV files with quoted fields for tabular output should consider converting the file beforehand with a specialized CSV parser like csvtool or miller into a clean, tab separated intermediate format, before applying column to it.
5. paste -d for custom delimiters and lines to columns
By default, paste uses a tab as the delimiter between the merged columns. With the -d option you can set your own delimiter, for example paste -d',' file_a.txt file_b.txt for a directly CSV compatible result. For tabular output that will be automatically processed further afterwards, a defined delimiter is often more practical than the default tab, because many downstream tools are explicitly built for commas or semicolons.
A particularly useful but less well known feature is the -s (serial) option, which completely reverses the behavior of paste: instead of combining several files line by line, -s merges all lines of a single file into a single line, separated by the character defined with -d. This is the exact counterpart to tr '\n' ',', but with the advantage that paste -s can cycle through several delimiters if more than one is specified with -d.
#!/usr/bin/env bash
set -euo pipefail
# Custom delimiter: comma instead of the default tab
paste -d',' names.txt emails.txt > contacts.csv
# Serial mode: turn every line of a file into one comma-separated line
paste -s -d',' one_value_per_line.txt
# Cycle between two delimiters: comma, then newline, repeating
paste -s -d',\n' pairs.txt
# Combine three sources with a custom separator for direct CSV output
paste -d',' server_names.txt cpu_percent.txt mem_percent.txt > server_report.csv
6. Practical example: building a monitoring report from several sources
A typical use case for tabular output in deployment and monitoring scripts: across several servers, a single report should show current CPU usage, memory consumption and disk usage. Each of these three metrics is queried separately via SSH on each server and written into its own temporary file, then paste combines the three files column by column, and column -t aligns the result for readable output in the terminal or in a Slack notification.
This pattern can be extended arbitrarily with further metrics, for example the number of running containers or the remaining lifetime of an SSL certificate, without needing to change the basic structure of the script. As long as every source delivers one line per server in the same order, paste correctly combines all columns, and column -t -N adds a readable header that makes the final report self explanatory even without additional documentation.
#!/usr/bin/env bash
set -euo pipefail
servers=(web01 web02 db01)
# Collect one metric per line for each server, in the same order
for host in "${servers[@]}"; do
echo "$host"
done > /tmp/hosts.txt
for host in "${servers[@]}"; do
ssh "$host" "top -bn1 | awk '/Cpu/{print \$2}'"
done > /tmp/cpu.txt
for host in "${servers[@]}"; do
ssh "$host" "free | awk '/Mem/{printf \"%.0f%%\", \$3/\$2*100}'"
done > /tmp/mem.txt
# Combine and format as a readable monitoring report
paste /tmp/hosts.txt /tmp/cpu.txt /tmp/mem.txt | column -t -N "Host,CPU%,Mem%"
7. Limits with very wide terminals and large datasets
A practical problem of tabular output with column -t shows up as soon as the total width of all columns exceeds the terminal width: lines wrap, which destroys the clean alignment again. In such cases, either reducing the displayed columns to the essentials helps, or redirecting the output into a file that can then be viewed horizontally scrollable with less -S, instead of wrapping automatically.
On very large datasets, keep in mind that column -t has to buffer the entire input to determine the maximum width of each column before the first line can be printed. For files in the millions of lines range, this can cause noticeable delays and high memory usage. In such cases, a fixed, predetermined column width with printf in awk or Bash is often the more practical alternative, because it works stream based and requires no complete buffering of the input.
8. Alternatives: column -J, pr and printf based formatting
Newer versions of column support -J for output as a JSON object instead of plain text, which is handy when the formatted data will be further processed by another program, without needing to parse the text back again. This option is interesting for modern tabular output workflows where the shell only serves as a data collector and the actual presentation happens in a web interface or another tool.
The older tool pr offers a different kind of formatting: multi column text output with page breaks, headers and footers, originally intended for printing on paper. For modern tabular output on screen, pr is rarely the first choice, but can be useful for automatically splitting long lists into several side by side columns, for example pr -3 -t list.txt for three columns side by side. For full control over formatting, number alignment and conditional formatting, printf inside awk or Bash remains the most flexible, if somewhat more elaborate, alternative.
9. Comparison: column/paste vs. awk printf for tabular output
For quick, ad hoc tabular output, column and paste are the right choice in most cases. But as soon as number formatting, conditional coloring, or fixed, unchangeable column widths are needed, printf shows its strength.
| Task | column/paste | awk printf | Recommendation |
|---|---|---|---|
| Quick ad hoc preview | column -t |
More typing | column, quicker to type |
| Combining several files | paste |
NR==FNR pattern needed | paste, the direct use case |
| Fixed, guaranteed column width | Depends on the longest value | %10s fixed by design |
printf for stability |
| Number formatting with decimals | Not designed for this | %10.2f |
printf, the only practical choice |
| Stream based on very large files | Buffers the entire input | Line by line output | printf, no memory concern |
For everyday use, tabular output with column and paste remains the most pragmatic solution, because both commands deliver directly readable results with minimal typing. But as soon as number formatting, guaranteed column widths, or very large datasets come into play, printf in awk or Bash is the more robust, if somewhat more elaborate, alternative.
Mironsoft
Monitoring scripts, reporting and shell automation
Combine monitoring data from several servers into one readable report?
We build reporting scripts that merge metrics from several sources and output them as a readable table in the terminal, by email or in Slack, without any additional dashboard tool.
Report scripts
Custom column/paste reports for monitoring and deployments
Automation
Setting up regular reports as a cron job with delivery
Training
Combining column, paste and printf correctly, taught to your team
10. Summary
Tabular output with column and paste solves an everyday problem in the shell: raw, delimited text data needs to be presented readably, without opening a spreadsheet or a graphical tool for it. column -t automatically aligns columns and accepts any delimiter with -s, paste combines several files line by line and, with -s, can even do the opposite, namely merge a file into a single line.
For tabular output with guaranteed column widths, number formatting, or very large datasets, printf in awk is the more robust choice, because it works stream based and offers full control over the output format. For quick, everyday use, however, column and paste remain the most pragmatic solution, because they deliver directly readable results with minimal effort.
Column and paste for tabular output: the essentials at a glance
column -t
Automatically aligns columns, -s defines the delimiter, -N sets header names.
paste
Combines files column by column line by line, -d sets the delimiter, -s merges lines into a single line.
Limits
Both buffer the entire input, on millions of lines a printf based alternative is more economical.
Alternatives
column -J for JSON output, pr for page based multi column formatting, printf for full control.