unexpand: Convert Spaces Back to Tabs
unexpand replaces sequences of spaces at tab stops with tab characters, the inverse of expand.
Some codebases and Makefiles require literal tabs. unexpand converts space indentation back to tabs so those files satisfy tools that demand them.
What it does
unexpand converts spaces to tabs. By default it only converts leading blanks; -a converts all runs of spaces that reach a tab stop. -t sets the tab width. It is the counterpart to expand and part of coreutils.
Common usage
# convert leading spaces back to tabs (Makefile fix)
unexpand -t 4 file.txt > file.tmp && mv file.tmp file.txt
# convert all space runs, not just leading
unexpand -a -t 8 file.txt
# Makefiles need real tabs on recipe lines
unexpand --first-only Makefile | sponge MakefileOptions
| Flag | What it does |
|---|---|
| -a, --all | Convert all runs of spaces, not just leading |
| -t <n> | Set tab width to n columns |
| --first-only | Convert only leading blanks (the default behavior) |
In CI
The classic use is fixing a "Makefile:12: *** missing separator" error, which means a recipe line is indented with spaces instead of a tab. unexpand --first-only -t 8 Makefile | sponge Makefile restores the tabs. As with expand, do not redirect over the input file directly.
Common errors in CI
"unexpand: tab size contains invalid character(s)" means a bad -t value. Without -a, only leading spaces are converted, so mid-line alignment stays as spaces (usually what you want for code). Redirecting unexpand f > f truncates the file; use a temp file or sponge. On Alpine install coreutils for the full option set.