Skip to content
Linux Basics: Reflow Plain-Text Paragraphs with GNU fmt

Linux Basics: Reflow Plain-Text Paragraphs with GNU fmt

October 25, 2026

A plain-text note can acquire uneven line lengths after several edits. GNU fmt reflows prose into paragraphs with a chosen line width. It can also limit reformatting to a comment prefix or split long lines without joining shorter ones.

These examples were tested on Linux with GNU Bash 5.2.37 and GNU coreutils 9.7. They use ASCII fixtures and LC_ALL=C so text layout is predictable. This is plain-text formatting, not a Markdown, source-code, or configuration-file parser.

Prepare a scratch directory

You need Bash, GNU fmt, a text editor, and the cat, mktemp, rm, and rmdir utilities. Keep using the same terminal. Stop on a setup failure before saving any example; the guards below enforce that. Save each named script here, then run each once in order.

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

1. Reflow paragraphs while keeping their separation

Save this as fmt-paragraphs.sh:

#!/usr/bin/env bash
set -eu
export LC_ALL=C
printf '%s\n' \
  'A small status report can start with uneven lines.' \
  'Keep related ideas in one paragraph for easier reading.' \
  '' \
  'A blank line starts a separate paragraph.' > paragraphs.txt
fmt --width=42 --goal=36 --uniform-spacing paragraphs.txt \
  > formatted.txt
cat formatted.txt

Run it:

bash fmt-paragraphs.sh

Output:

A small status report can start with
uneven lines.  Keep related ideas in
one paragraph for easier reading.

A blank line starts a separate paragraph.

The adjacent source lines are prose in the same paragraph, so fmt can join and redistribute their words. The blank line preserves the break between paragraphs. The original file remains unchanged because the output is written to a different file.

--width supplies the maximum target width and --goal supplies the preferred width. --uniform-spacing uses one space between words and two after recognized sentence endings. Omit it when you do not want that spacing policy. The GNU fmt manual packaged by Debian describes these options.

The width is not a request to pad every line. Short final lines are normal, and an indivisible word longer than the width can still exceed it.

2. Reflow only lines with a chosen comment prefix

Save this as fmt-prefixed-comments.sh:

#!/usr/bin/env bash
set -eu
export LC_ALL=C
printf '%s\n' \
  '# Keep this explanation readable when it is copied into a plain text note.' \
  '# The next comment belongs to the same paragraph.' \
  'mode = preview' \
  '# This is a separate comment after the setting.' > comments.txt
fmt --prefix='# ' --width=42 --goal=36 comments.txt

Run it:

bash fmt-prefixed-comments.sh

Output:

# Keep this explanation readable when
# it is copied into a plain text note.
# The next comment belongs to the
# same paragraph.
mode = preview
# This is a separate comment after
# the setting.

The prefix is removed for reformatting and attached again to the resulting comment lines. The nonmatching setting line is passed through rather than joined into the comment paragraph. This is convenient for a small, controlled block of prose with a consistent marker.

Prefix matching does not understand the surrounding language. A comment might contain a URL, an example command, indentation, or other formatting that should not be reflowed. Select the prose you intend to change and review the result instead of running this blindly over a real configuration file.

3. Split long lines without joining short ones

Save this as fmt-split-only.sh:

#!/usr/bin/env bash
set -eu
export LC_ALL=C
printf '%s\n' \
  'Short heading' \
  'This longer explanation should wrap without being joined to the heading.' \
  'End note' > separate-lines.txt
fmt --split-only --width=34 --goal=30 separate-lines.txt
printf 'An indivisible token:\n'
printf '%s\n' 'abcdefghijklmnopqrstuvwxyz0123456789' \
  | fmt --split-only --width=12

Run it:

bash fmt-split-only.sh

Output:

Short heading
This longer explanation should
wrap without being joined to
the heading.
End note
An indivisible token:
abcdefghijklmnopqrstuvwxyz0123456789

--split-only keeps existing line boundaries instead of filling paragraphs across them. The long explanation can become several lines, while the short heading and final note stay separate. It is a useful choice when the existing breaks carry meaning but long prose still needs wrapping.

The last input is a single uninterrupted token. fmt leaves it intact even though it exceeds the requested width. It breaks text at word boundaries rather than inserting arbitrary breaks inside words. If a downstream format requires a hard byte or column limit, validate that requirement separately instead of treating fmt as an enforcement step.

Keep in mind

Reflowing is a content transformation: existing whitespace and line breaks can change. Use it for prose, not aligned tables, source code, preformatted examples, or a format whose whitespace has meaning. Multibyte text and terminal display widths also need testing with the locale and data you actually use.

Keep input and output filenames different. Shell redirection opens the destination before the command runs, so using the same file for both can destroy the source text before it is read.

Clean up

Remove only the named practice files and return to your original directory:

rm -- fmt-paragraphs.sh fmt-prefixed-comments.sh fmt-split-only.sh \
  paragraphs.txt formatted.txt comments.txt separate-lines.txt
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

Acknowledgements

This post was created with assistance from AI.

Last updated on