Text processing
expand
Convert tabs to spaces, keeping the columns where they were; unexpand does the reverse.
expand [OPTION...] [FILE...]
expand replaces each tab with the number of spaces needed to reach the next tab stop, so the
text looks exactly as it did but contains no tabs. Tab stops are every 8 columns by default;
-t 4 makes them every 4, and a list like -t 10,20 sets explicit positions.
This matters when tabs render differently in different places: code reviews, web pages,
terminals with other tab settings, or tools that count characters. Its companion unexpand
(same package) turns leading runs of spaces back into tabs.
Examples
Replace tabs with spaces
expand data/inventory.tsv | cat -A
name qty price$ widget 12 4.50$ gadget 3 19.99$ gizmo 5 12.00$
cat -A would show tabs as ^I; there are none left. Each tab became enough spaces to reach
the next multiple of 8, so qty starts at column 9 on every line.
Tab stops every 4 columns
printf 'if ok:\n\tif ready:\n\t\treturn 1\n' | expand -t 4
if ok:
if ready:
return 1 -t 4 treats each tab as up to 4 columns, the usual setting for code that was indented with tabs.
Tab stops at explicit positions
expand -t 10,16 data/inventory.tsv
name qty price widget 12 4.50 gadget 3 19.99 gizmo 5 12.00
With a list, the first tab on each line goes to column 10 and the second to column 16, giving a fixed-width table.
Convert only leading tabs
printf '\tkey\tvalue\n' | expand -i -t 4 | cat -A
key^Ivalue$
-i expands only the tabs in the indentation; the tab between key and value survives
(^I). Useful when tabs inside strings must stay.
Turn leading spaces back into tabs
printf ' eight spaces\n' | unexpand -t 4 | cat -A
^I^Ieight spaces$
unexpand -t 4 converts each 4 leading spaces into a tab, so 8 spaces become ^I^I.
Convert a file in place
expand -t 4 data/inventory.tsv > inventory.txt && mv inventory.txt data/inventory.tsv
grep -c $'\t' data/inventory.tsv
0
expand cannot edit a file in place, so write to a new file and rename it. Afterwards
grep -c finds 0 lines with a tab, and exits with 1 because nothing matched.
Common pitfalls
expand file > fileempties the file beforeexpandreads it. Write to a temporary file andmvit back.Expanding tabs in a Makefile breaks it: recipe lines must start with a real tab. Use
expand -icarefully there, or not at all.unexpandwithout-aonly converts leading blanks; pass-ato convert runs of spaces everywhere on the line.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
expand -tandunexpand -t/-awork on both GNU and BSD/macOS;-i(initial tabs only) is GNU.
Options worth knowing
A selection, described in our own words. For the full list, see expand(1) or expand --help.
| Option | What it does |
|---|---|
-t, --tabs N|LIST | Tab stops every N columns, or at the listed column positions. |
-i, --initial | Only convert tabs before the first non-blank character. |
Related
columnFormat input into aligned columns or a table; turns CSV and whitespace data into readable output.catConcatenate files and print them to standard output; also the quickest way to see a short file.sedEdit a stream of text with a script of commands, most often to substitute text or delete lines.trTranslate, squeeze or delete characters from standard input; for case changes, line endings and stripping characters.