How to Use fold fmt and nl to Format Text Without Surprises
Use fold, fmt and nl to wrap lines, reflow paragraphs and number text from the terminal, and know which one breaks words, which respects them, and why.

Three small utilities from coreutils handle most text shaping that does not need a regular expression. They are easy to confuse: one cuts, one reflows and one counts. Used with the tools in cut and wc, they cover quick formatting for emails, commit messages and reports. The examples assume GNU coreutils 9.x.
fold: cut at a width
echo "The quick brown fox jumps over the lazy dog near the river bank" | fold -w 24
echo "The quick brown fox jumps over the lazy dog near the river bank" | fold -s -w 24The quick brown fox jump
s over the lazy dog near
the river bank
The quick brown fox
jumps over the lazy dog
near the river bank
Plain fold splits at the column even in the middle of a word. -s breaks at the last space within the width, which is almost always what you want for prose. It does not rejoin anything: short lines stay short. Use -b to count bytes when the input has multibyte characters you want to split safely.
fmt: reflow paragraphs
cat notes.txt
fmt -w 40 notes.txtThis is a short
line. And another short
one.
Second paragraph here.
This is a short line. And another short
one.
Second paragraph here.
fmt reads paragraphs separated by blank lines, joins their lines and rewraps them to the width. The default width is 75. It preserves the indentation of the first two lines of each paragraph, so an indented block stays indented, and -u normalises spacing to one space between words. In Vim, gq over a block does the same; fmt is the filter form for pipelines, like wrapping a commit message body to 72 columns.
nl: number lines
printf 'alpha\n\nbeta\ngamma\n' | nl
printf 'alpha\n\nbeta\ngamma\n' | nl -ba
printf 'alpha\n\nbeta\ngamma\n' | nl -ba -w3 -s': ' 1 alpha
2 beta
3 gamma
1 alpha
2
3 beta
4 gamma
1: alpha
2:
3: beta
4: gamma
By default nl numbers only non-empty lines (style t), which surprises people who expect cat -n. -ba numbers all lines, -w sets the number width and -s sets the separator. Cut pages into sections with -h, -b and -f options when the input has section delimiters, a feature few people need.
Combining them
fmt -w 60 README.txt | nl -ba | less
fold -s -w 80 long-log-line.txt | head -20Reflow first, then number, and the numbers refer to the wrapped lines. To read a file with very long lines in a pager, fold -s beats horizontal scrolling, and less can also wrap with -S toggled off. When you need columns rather than a flow of text, use cut, paste and column.
fold and the problem of wrapping words
The fold command breaks long lines at a fixed width. By default it cuts exactly at the column limit, in the middle of a word if that is where the limit falls. The -s option breaks at the last space before the limit instead, which gives readable output for prose. Width counts columns in bytes by default in GNU fold, with -b making the byte counting explicit, so multibyte text can be broken in the middle of a character unless the locale is set to UTF-8, and even then wide characters such as CJK take two columns on screen. For text with such content, check the output rather than trusting the count.
A typical use is preparing a commit message body or an email to wrap at 72 columns: fold -s -w 72. For code and logs, folding is usually a mistake, since it breaks tokens and makes lines harder to search.
fmt reflows paragraphs
Where fold cuts lines mechanically, fmt treats text as paragraphs. It joins short lines in a paragraph, splits long ones, and keeps blank lines as paragraph breaks. The target width is set with -w, and the default is 75. Indentation of the first two lines is preserved, which keeps a hanging indent on bulleted text, and -p PREFIX reflows only lines that start with a prefix such as a comment marker, leaving code alone. That makes fmt -p '# ' a handy way to rewrap a comment block in a script.
The -u option produces uniform spacing, one space between words and two after a sentence. Use -s to split long lines but not join short ones, which suits text where every line break matters. Check what each option does on sample text, since the interactions are subtle and the manual page is brief.
nl and the options that matter
The nl command numbers lines, with more control than cat -n. It distinguishes the header, body and footer sections of a logical page and by default numbers only non-empty lines of the body. Options include -b a to number all lines, -w for the width of the number field, -s for the separator after the number and -n for the justification, such as rz for right-justified with leading zeros. Blank lines are skipped by default, which can surprise someone expecting every line to receive a number.
Line numbers help when discussing a configuration file, referring to a place in a log or building a quick cross-reference, as in nl -ba file | sed -n '40,60p'. For file viewing, less -N shows numbers without changing the file, and grep -n includes the original line numbers in its matches.
Combining them in pipelines
These tools compose with others. To reflow a file and number the lines, pipe fmt into nl. To produce a fixed-width column of text for a terminal, fold -s -w "$(tput cols)" adapts to the terminal width, though terminals that wrap by themselves rarely need it. In scripts that format text for a fixed-width medium, such as an SMS gateway or a legacy system, fold and fmt are sturdier than hand-written loops. Always test with a long unbroken string and with empty input; both are common edge cases, and the behaviour differs between GNU and BSD versions, which matters on macOS where the options are fewer.
Remember that these commands read standard input, so in a pipeline they process the stream in order. They are cheap enough for any file that fits in a pipe, and the main risk is wrapping text that should not be wrapped.
These utilities also differ in how they treat tabs and trailing spaces. fold counts a tab as advancing to the next multiple of eight columns only with the -s and column-aware options, and fmt converts tabs to spaces when it reflows. If the input mixes tabs and spaces, normalise with expand first so the widths mean what you expect. Check output in a plain text file with a ruler line above it when exact widths matter, and keep the commands in a small script so the same settings are used each time the text is prepared.
Where this does not apply
None of these understand markup: fmt will happily rewrap a Markdown list or a code block and ruin it, so do not run it over a whole document. East Asian wide characters take two columns in a terminal but count as one for fold and fmt, so alignment drifts. For display in a fixed-width box, a tool like par or a script with a Unicode-aware library does better. See the GNU fmt manual, the fold manual and the nl manual.


