Linux Command Reference

fmt

Synopsis

fmt [OPTION]... [FILE]... fmt [-WIDTH] [FILE]...

Description

The fmt command reformats text to fit within a specified line width, breaking long lines and filling short ones to create uniform paragraph formatting. It's the Unix equivalent of a word processor's "reflow" function - taking ragged, irregular text and making it neat and readable at a specified width (default 75 characters).

Originally designed for formatting email and text files before sophisticated word processors existed, fmt remains invaluable for cleaning up text documentation, formatting README files, preparing text for email clients, and wrapping code comments. It intelligently preserves paragraph breaks, handles indentation, and can maintain uniform spacing between words, making it perfect for automated text cleanup in scripts and pipelines.

Key Concepts

Detailed Examples

Example 1

Basic Text Wrapping

Use fmt with default settings to reformat text to 75 characters width. This is the most common use case - taking messy text and making it readable with consistent line lengths.
# Create sample text with irregular line lengths cat > messy.txt << 'EOF' This is a very long line that extends way beyond what would be considered reasonable for reading on most displays and should definitely be wrapped to a more manageable width. This is short. Another really long line here that goes on and on and on without any breaks which makes it difficult to read especially in terminals with limited width or in email clients. This is a new paragraph. It also has some long lines that need formatting. EOF # Basic fmt - default 75 character width fmt messy.txt # Format and save to new file fmt messy.txt > formatted.txt # Format from stdin cat messy.txt | fmt # Format multiple files fmt file1.txt file2.txt file3.txt # View before and after echo "=== BEFORE ===" cat messy.txt echo "" echo "=== AFTER ===" fmt messy.txt
Output:
This is a very long line that extends way beyond what would be considered reasonable for reading on most displays and should definitely be wrapped to a more manageable width. This is short. Another really long line here that goes on and on and on without any breaks which makes it difficult to read especially in terminals with limited width or in email clients. This is a new paragraph. It also has some long lines that need formatting.
Note:

fmt joins short lines within a paragraph but breaks long ones. Blank lines delimit paragraphs - each paragraph is formatted independently. Default width is 75 characters, suitable for most email clients and terminals.

Example 2

Specifying Custom Width

Change the output width using -w (--width) or the shorthand numeric option. Different widths suit different purposes - narrow for email, wide for documentation, specific widths for terminal or editor constraints.
# Create sample text cat > sample.txt << 'EOF' The quick brown fox jumps over the lazy dog. This sentence is repeated multiple times to demonstrate how fmt wraps text at different widths. The quick brown fox jumps over the lazy dog again and again. EOF # Format to 40 characters (narrow, good for email) echo "=== 40 characters ===" fmt -w 40 sample.txt # Format to 60 characters echo "=== 60 characters ===" fmt -w 60 sample.txt # Format to 100 characters (wide, good for documentation) echo "=== 100 characters ===" fmt -w 100 sample.txt # Shorthand notation (no -w needed) echo "=== Using shorthand -50 ===" fmt -50 sample.txt # Very narrow (useful for side-by-side comparisons) echo "=== 30 characters ===" fmt -30 sample.txt # Practical: format for 80-column terminal fmt -80 README.txt > README.formatted.txt # Format git commit message to standard 72 chars git log -1 --pretty=%B | fmt -72
Output:
=== 40 characters === The quick brown fox jumps over the lazy dog. This sentence is repeated multiple times to demonstrate how fmt wraps text at different widths. The quick brown fox jumps over the lazy dog again and again. === 60 characters === The quick brown fox jumps over the lazy dog. This sentence is repeated multiple times to demonstrate how fmt wraps text at different widths. The quick brown fox jumps over the lazy dog again and again. === 100 characters === The quick brown fox jumps over the lazy dog. This sentence is repeated multiple times to demonstrate how fmt wraps text at different widths. The quick brown fox jumps over the lazy dog again and again. === 30 characters === The quick brown fox jumps over the lazy dog. This sentence is repeated multiple times to demonstrate how fmt wraps text at different widths. The quick brown fox jumps over the lazy dog again and again.
Note:

Common widths: 72 for git commits, 75-80 for general text, 60 for email, 100+ for documentation. The shorthand fmt -WIDTH is equivalent to fmt -w WIDTH and is more commonly used.

Example 3

Uniform Spacing (-u)

Use the -u flag to create uniform spacing: single space between words, double space after sentence-ending punctuation. This produces more traditional, typographically correct formatting.
# Create text with irregular spacing cat > spacing.txt << 'EOF' This has irregular spacing. Multiple spaces between words. See? Also after periods.Here's another sentence.And another. EOF # Default fmt (preserves some spacing irregularities) echo "=== Default formatting ===" fmt spacing.txt # Uniform spacing echo "=== With -u (uniform) ===" fmt -u spacing.txt # Compare side by side echo "=== Comparison ===" echo "Without -u:" fmt spacing.txt echo "" echo "With -u:" fmt -u spacing.txt # Practical: clean up pasted text with weird spacing pbpaste | fmt -u -w 72 | pbcopy # macOS # xclip -o | fmt -u -w 72 | xclip -i # Linux # Format email text with proper spacing cat email_draft.txt | fmt -u -60 > email_formatted.txt
Output:
=== Default formatting === This has irregular spacing. Multiple spaces between words. See? Also after periods.Here's another sentence.And another. === With -u (uniform) === This has irregular spacing. Multiple spaces between words. See? Also after periods. Here's another sentence. And another. === Comparison === Without -u: This has irregular spacing. Multiple spaces between words. See? Also after periods.Here's another sentence.And another. With -u: This has irregular spacing. Multiple spaces between words. See? Also after periods. Here's another sentence. And another.
Note:

The -u flag enforces classic typography: one space between words, two after sentence-ending punctuation (. ! ?). This makes text more readable and professionally formatted. Especially useful for cleaning up text copied from various sources.

Example 4

Preserving Indentation

Use -p or -t to preserve indentation patterns. This is essential for formatting text that uses indentation for structure, like nested lists, code comments, or quoted text.
# Create indented text cat > indented.txt << 'EOF' First level paragraph with some text that needs to be formatted. Second level indented paragraph that also has some long text that should be wrapped while preserving the indentation. Third level even more indented text here that definitely needs wrapping. Different indent paragraph with just two spaces instead of four. EOF # Without preserving indentation (flattens everything) echo "=== Without -p ===" fmt -60 indented.txt # Preserve indentation with -p echo "=== With -p (preserve indentation) ===" fmt -p -60 indented.txt # Tagged paragraphs with -t (crown margin) cat > tagged.txt << 'EOF' 1. This is the first item in a numbered list that has text long enough to demonstrate how fmt handles crown margins. 2. This is the second item with similarly long text. 3. Third item here. EOF echo "=== Tagged with -t ===" fmt -t -60 tagged.txt # Practical: format email replies preserving > quotes cat > email_reply.txt << 'EOF' > Original message here that was sent to me and I'm replying to it with some commentary. > The original goes on for a while. My response to the above message with my own lengthy commentary that needs formatting. EOF fmt -p '>' -60 email_reply.txt # Format code comments preserving indentation cat > code_comments.c << 'EOF' /* This is a long comment that extends beyond reasonable width and should be reformatted while maintaining indentation */ // Another comment style that's too long for the screen EOF fmt -p -80 code_comments.c
Output:
=== Without -p === First level paragraph with some text that needs to be formatted. Second level indented paragraph that also has some long text that should be wrapped while preserving the indentation. Third level even more indented text here that definitely needs wrapping. Different indent paragraph with just two spaces instead of four. === With -p (preserve indentation) === First level paragraph with some text that needs to be formatted. Second level indented paragraph that also has some long text that should be wrapped while preserving the indentation. Third level even more indented text here that definitely needs wrapping. Different indent paragraph with just two spaces instead of four. === Tagged with -t === 1. This is the first item in a numbered list that has text long enough to demonstrate how fmt handles crown margins. 2. This is the second item with similarly long text. 3. Third item here.
Note:

The -p flag preserves indentation throughout the paragraph. The -t flag creates "crown margin" style where the first line indent differs from subsequent lines - perfect for numbered lists and bullet points. Use -p 'PREFIX' to preserve lines starting with PREFIX (like email quotes).

Example 5

Formatting Multiple Paragraphs

fmt handles multiple paragraphs intelligently, reformatting each independently while preserving paragraph breaks. This is essential for document formatting where structure must be maintained.
# Create multi-paragraph document cat > document.txt << 'EOF' INTRODUCTION This is the introduction paragraph. It contains some important information that extends across multiple lines and needs proper formatting for readability. METHODOLOGY The methodology section describes our approach. This paragraph also has text that is quite long and irregular, with some lines being very long and others quite short. Like this one. And this. RESULTS Our results show significant findings. The data indicates a clear trend across all measurements taken during the study period. CONCLUSION In conclusion, we can state with confidence that the hypothesis was supported by the data. Further research is needed to explore additional dimensions of this phenomenon. EOF # Format the entire document fmt -70 document.txt # Save formatted version fmt -70 document.txt > document_formatted.txt # Format with uniform spacing fmt -u -70 document.txt # Compare paragraph handling echo "=== Original paragraph structure ===" grep -c '^$' document.txt echo "blank lines" echo "=== After formatting ===" fmt -70 document.txt | grep -c '^$' echo "blank lines (preserved)" # Practical: format markdown file preserving structure cat README.md | fmt -80 > README.formatted.md # Format but preserve multiple blank lines awk 'BEGIN{blank=0} /^$/ {blank++; if(blank<=2) print; next} {blank=0; print}' document.txt | fmt -70
Output:
INTRODUCTION This is the introduction paragraph. It contains some important information that extends across multiple lines and needs proper formatting for readability. METHODOLOGY The methodology section describes our approach. This paragraph also has text that is quite long and irregular, with some lines being very long and others quite short. Like this one. And this. RESULTS Our results show significant findings. The data indicates a clear trend across all measurements taken during the study period. CONCLUSION In conclusion, we can state with confidence that the hypothesis was supported by the data. Further research is needed to explore additional dimensions of this phenomenon.
Note:

fmt preserves blank lines between paragraphs but merges lines within paragraphs. Multiple consecutive blank lines are reduced to single blank lines. Section headers that are separate paragraphs remain separate. This maintains document structure while improving readability.

Example 6

Email Formatting

Format email text including quoted replies, maintaining proper quote markers and indentation. This is one of fmt's original and most important use cases - making email readable.
# Create email with quoted text cat > email.txt << 'EOF' Hi John, > Thanks for your email. I wanted to respond to your question about the project timeline and deliverables. Here's my understanding of where we are. I appreciate your response. However, I think we need to reconsider the timeline because of the recent changes to the requirements. > > The original deadline was set for December 15th based on the initial scope. > > > > Can we still meet that deadline? > I believe we can if we prioritize the core features and defer the nice-to-haves to a later phase. That sounds reasonable. Let me know what you think about moving forward with this approach. Thanks, Craig EOF # Format email preserving quote markers fmt -w 72 email.txt # Better: preserve indentation for quotes fmt -p '>' -w 72 email.txt # Format with uniform spacing fmt -u -p '>' -w 72 email.txt # Handle multiple quote levels cat > complex_email.txt << 'EOF' > Original sender wrote: > > Previous person said something > > that was quite lengthy > > First reply adding more text > that needs formatting My response here EOF fmt -p '>' -w 60 complex_email.txt # Practical: format email before sending compose_email() { cat > /tmp/email_draft.txt << 'EOF' Your email content here... EOF # Format and display fmt -u -p '>' -w 72 /tmp/email_draft.txt } # Clean up pasted email pbpaste | fmt -u -p '>' -w 72 | pbcopy
Output:
Hi John, > Thanks for your email. I wanted to respond to your question > about the project timeline and deliverables. Here's my > understanding of where we are. I appreciate your response. However, I think we need to reconsider the timeline because of the recent changes to the requirements. > > The original deadline was set for December 15th based on > > the initial scope. > > > > Can we still meet that deadline? > I believe we can if we prioritize the core features and defer > the nice-to-haves to a later phase. That sounds reasonable. Let me know what you think about moving forward with this approach. Thanks, Craig
Note:

Email quote markers (>) are preserved with -p '>'. Multiple quote levels (>>) are handled correctly. Standard email width is 72 characters for compatibility with various email clients. Use -u for clean, consistent spacing.

Example 7

Code Comment Formatting

Format code comments to fit within line width limits while preserving indentation and comment markers. Useful for keeping code readable and meeting style guide requirements.
# Create code with long comments cat > sample.py << 'EOF' # This is a really long comment that extends way beyond the recommended 79 character limit for Python code and really should be wrapped to multiple lines for better readability def process_data(input_file, output_file): """This docstring is also quite long and extends beyond reasonable width making it hard to read in standard editor windows or when viewing code on GitHub""" pass # Another long comment here that talks about the implementation details and why we chose this particular approach for handling edge cases EOF # Format Python comments (preserve # and indentation) awk '/^#/ || /^ #/ || /^"""/ {print; next} {print}' sample.py | \ fmt -p '#' -w 79 # Format C-style comments cat > sample.c << 'EOF' /* This is a very long C comment that extends beyond the typical 80 character line limit and should be wrapped for better readability in the source code */ int main() { // Inline comment that is also quite long and extends past reasonable width for code review return 0; } EOF # Preserve /* and // markers sed 's|^/\*|/\* |' sample.c | fmt -w 78 | sed 's|/\* |/\*|' # Format shell script comments cat > script.sh << 'EOF' #!/bin/bash # This is a long comment in a shell script that explains what the script does and why it was written this way and what assumptions it makes about the environment echo "Hello" EOF fmt -p '#' -w 78 script.sh # Practical: format all comments in a file format_comments() { local file="$1" local width="${2:-79}" case "$file" in *.py) fmt -p '#' -w "$width" "$file" ;; *.sh) fmt -p '#' -w "$width" "$file" ;; *.c|*.cpp) # Handle C-style comments fmt -w "$width" "$file" ;; *) echo "Unknown file type" return 1 ;; esac } format_comments sample.py 79
Output:
# Python formatted: # This is a really long comment that extends way beyond the # recommended 79 character limit for Python code and really should be # wrapped to multiple lines for better readability def process_data(input_file, output_file): """This docstring is also quite long and extends beyond reasonable width making it hard to read in standard editor windows or when viewing code on GitHub""" pass # Another long comment here that talks about the implementation # details and why we chose this particular approach for handling # edge cases # C formatted: /* This is a very long C comment that extends beyond the typical 80 character line limit and should be wrapped for better readability in the source code */ int main() { // Inline comment that is also quite long and extends past // reasonable width for code review return 0; }
Warning:

Be careful when reformatting code files. fmt doesn't understand code syntax and might break strings or other code elements. Use it selectively on comments, not entire code files. Consider using language-specific formatters for comprehensive code formatting.

Example 8

Pipeline Integration

Use fmt in pipelines with other commands for sophisticated text processing. Combine with grep, sed, awk, and other tools to create powerful text manipulation workflows.
# Extract and format specific sections cat document.txt | \ awk '/RESULTS/,/CONCLUSION/ {print}' | \ fmt -70 # Format git commit messages git log --pretty=format:"%B" -1 | fmt -72 # Format man page output to narrow width man bash | col -b | fmt -60 | less # Clean up and format pasted text # macOS: pbpaste | fmt -u -w 72 | pbcopy # Linux: xclip -o | fmt -u -w 72 | xclip -i # Format extracted quotes grep "^> " email.txt | \ sed 's/^> //' | \ fmt -60 | \ sed 's/^/> /' # Create formatted documentation from code grep -h "^#" *.sh | \ sed 's/^# //' | \ fmt -u -80 > script_documentation.txt # Format SQL comments cat query.sql | \ grep "^--" | \ sed 's/^-- //' | \ fmt -70 | \ sed 's/^/-- /' # Combine multiple text files and format cat intro.txt body.txt conclusion.txt | \ fmt -u -75 > complete_document.txt # Format stdin with automatic line numbering fmt -60 input.txt | nl -ba # Create formatted README from template cat README.template | \ envsubst | \ fmt -u -80 > README.md # Format and preview fmt -70 document.txt | \ pr -h "Formatted Document" | \ less
Pipeline examples output:
# Git commit formatted to 72 chars: Add new feature for data processing This commit introduces a new data processing feature that significantly improves performance when handling large datasets. The implementation uses a streaming approach to reduce memory usage. # Formatted man page (narrow for side-by-side viewing): BASH(1) General Commands Manual NAME bash - GNU Bourne-Again SHell SYNOPSIS bash [options] [command_string | file] # Formatted quotes: > Thanks for the detailed explanation. I understand > the approach now and think we should proceed with > this implementation. # Documentation from scripts: This script processes log files and generates reports. It takes an input directory and output file as arguments. The script handles various log formats including Apache and nginx.
Note:

fmt works seamlessly in pipelines. Common patterns: extract text with grep/awk, clean with sed, format with fmt. Remember fmt reads stdin when no file is given, making it perfect for pipeline usage. Combine with tee to save intermediate results.

Example 9

Configuration File Formatting

Format configuration files and documentation while preserving structure. Useful for README files, config file comments, and maintaining readable documentation in text format.
# Create config with long comments cat > app.conf << 'EOF' # Database configuration section - This section contains all database-related settings including connection strings, timeouts, and pool sizes database.host=localhost database.port=5432 # Cache configuration - These settings control how the application caches data and for how long cached entries remain valid before expiration cache.ttl=3600 cache.max_size=1000 # Logging configuration - Control verbosity and output destinations for application logs including file rotation policies log.level=INFO log.file=/var/log/app.log EOF # Format only comments awk '/^#/ {comment=$0; getline; print comment; print} !/^#/ {print}' app.conf | \ fmt -p '#' -w 70 # Format README sections cat > README.txt << 'EOF' # Installation To install this application you need to first download the source code from the repository then run the installation script which will compile the code and install all necessary dependencies. # Configuration The application can be configured through the main configuration file located in /etc/app/config.yml where you can set various parameters. # Usage Run the application with the --help flag to see all available options and their descriptions. EOF # Format keeping headers intact awk '/^# / {print; next} /^$/ {print; next} {para=para $0 " "; next} END {if (para) print para}' README.txt | \ fmt -w 72 # Practical: format Dockerfile comments cat > Dockerfile << 'EOF' FROM ubuntu:20.04 # Install system dependencies - This includes all the base packages needed for building and running the application including compilers and libraries RUN apt-get update && apt-get install -y build-essential # Copy application files and set up the working directory for the application to run from COPY . /app WORKDIR /app EOF fmt -p '#' -w 75 Dockerfile # Format INI file comments cat > settings.ini << 'EOF' [General] ; This is the general configuration section where you can set application-wide parameters that affect overall behavior app_name=MyApp version=1.0.0 [Database] ; Database connection settings including host, port, credentials and connection pooling parameters for optimal performance host=localhost port=5432 EOF fmt -p ';' -w 70 settings.ini # Format YAML comments cat > config.yml << 'EOF' # Server configuration # This section defines how the server should behave including which port to listen on and what hostname to use for external connections server: port: 8080 host: 0.0.0.0 # Security settings # Configure authentication and authorization including session timeouts and encryption parameters security: session_timeout: 3600 EOF fmt -p '#' -w 70 config.yml
Output:
# Formatted config: # Database configuration section - This section contains all # database-related settings including connection strings, # timeouts, and pool sizes database.host=localhost database.port=5432 # Cache configuration - These settings control how the # application caches data and for how long cached entries remain # valid before expiration cache.ttl=3600 cache.max_size=1000 # Formatted README: # Installation To install this application you need to first download the source code from the repository then run the installation script which will compile the code and install all necessary dependencies. # Configuration The application can be configured through the main configuration file located in /etc/app/config.yml where you can set various parameters. # Formatted Dockerfile: FROM ubuntu:20.04 # Install system dependencies - This includes all the base # packages needed for building and running the application # including compilers and libraries RUN apt-get update && apt-get install -y build-essential
Note:

When formatting config files, use -p to preserve comment markers (#, ;, //). Be careful not to format actual config values - only comments and documentation. Consider using awk to selectively format only comment lines while leaving config directives unchanged.

Example 10

Document Formatting Automation Script

A comprehensive script that automates document formatting with configurable options, multiple format detection, and quality checks. Production-ready for batch processing text files.
#!/bin/bash # File: format_docs.sh # Automated document formatting with fmt set -euo pipefail # ============================================ # Configuration # ============================================ readonly DEFAULT_WIDTH=75 readonly DEFAULT_OPTIONS="-u" readonly BACKUP_SUFFIX=".bak" readonly LOG_FILE="format_docs.log" # ============================================ # Logging # ============================================ log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE" } # ============================================ # File Type Detection # ============================================ detect_comment_prefix() { local file="$1" local ext="${file##*.}" case "$ext" in py|sh|bash|yaml|yml|rb) echo "#" ;; c|cpp|h|hpp|java|js|ts|go) echo "//" ;; ini|conf) echo ";" ;; *) echo "" ;; esac } # ============================================ # Formatting Functions # ============================================ format_file() { local file="$1" local width="${2:-$DEFAULT_WIDTH}" local preserve_indent="${3:-no}" local uniform="${4:-yes}" log "Formatting: $file (width: $width)" # Detect if file has structure that needs preservation local comment_prefix=$(detect_comment_prefix "$file") # Build fmt command local fmt_cmd="fmt" # Add width fmt_cmd="$fmt_cmd -w $width" # Add uniform spacing if requested if [ "$uniform" = "yes" ]; then fmt_cmd="$fmt_cmd -u" fi # Add prefix preservation if detected if [ -n "$comment_prefix" ]; then fmt_cmd="$fmt_cmd -p '$comment_prefix'" elif [ "$preserve_indent" = "yes" ]; then fmt_cmd="$fmt_cmd -p" fi # Create backup cp "$file" "${file}${BACKUP_SUFFIX}" # Format file eval "$fmt_cmd" "$file" > "${file}.tmp" # Check if formatting produced valid output if [ -s "${file}.tmp" ]; then mv "${file}.tmp" "$file" log " Success: $file formatted" return 0 else log " Error: Formatting produced empty file, restoring backup" mv "${file}${BACKUP_SUFFIX}" "$file" rm -f "${file}.tmp" return 1 fi } # ============================================ # Quality Checks # ============================================ check_line_lengths() { local file="$1" local max_width="${2:-$DEFAULT_WIDTH}" local longest=$(awk '{print length}' "$file" | sort -rn | head -1) if [ "$longest" -le "$max_width" ]; then log " ✓ All lines within $max_width characters (longest: $longest)" return 0 else log " ⚠ Some lines exceed $max_width characters (longest: $longest)" return 1 fi } check_paragraph_structure() { local file="$1" local para_count=$(awk 'BEGIN{para=0} /^$/{para++} END{print para}' "$file") log " Paragraphs: $para_count" } # ============================================ # Batch Processing # ============================================ format_directory() { local dir="$1" local width="${2:-$DEFAULT_WIDTH}" local pattern="${3:-*.txt}" log "=========================================" log "Batch formatting: $dir" log "Pattern: $pattern" log "Width: $width" log "=========================================" local total=0 local success=0 local failed=0 while IFS= read -r -d '' file; do ((total++)) if format_file "$file" "$width"; then ((success++)) check_line_lengths "$file" "$width" else ((failed++)) fi done < (find "$dir" -name "$pattern" -type f -print0) log "=========================================" log "Summary:" log " Total files: $total" log " Successful: $success" log " Failed: $failed" log "=========================================" } # ============================================ # Report Generation # ============================================ generate_report() { local dir="$1" local report_file="formatting_report.txt" { echo "Document Formatting Report" echo "Generated: $(date)" echo "Directory: $dir" echo "" echo "Files Processed:" echo "================" find "$dir" -name "*.txt" -type f | while read -r file; do local lines=$(wc -l < "$file") local longest=$(awk '{print length}' "$file" | sort -rn | head -1) local words=$(wc -w < "$file") printf "%-40s %5d lines %3d max %6d words\n" \ "$(basename "$file")" "$lines" "$longest" "$words" done echo "" echo "Formatting Statistics:" echo "=====================" awk 'BEGIN{total=0; success=0; failed=0} /Formatting:/ {total++} /Success:/ {success++} /Error:/ {failed++} END { print "Total files processed:", total print "Successfully formatted:", success print "Failed:", failed if (total > 0) { printf "Success rate: %.1f%%\n", (success/total)*100 } }' "$LOG_FILE" } > "$report_file" cat "$report_file" log "Report saved to: $report_file" } # ============================================ # Main # ============================================ usage() { cat << EOF Usage: $(basename "$0") [OPTIONS] [FILE|DIRECTORY] Options: -w WIDTH Line width (default: $DEFAULT_WIDTH) -p Preserve indentation -d Directory mode (process all .txt files) -r Generate report -h Show this help Examples: $(basename "$0") document.txt $(basename "$0") -w 80 document.txt $(basename "$0") -d -w 72 /path/to/docs $(basename "$0") -r /path/to/docs EOF } main() { local width=$DEFAULT_WIDTH local preserve_indent="no" local directory_mode="no" local generate_report_flag="no" # Parse options while getopts "w:pdrh" opt; do case $opt in w) width="$OPTARG" ;; p) preserve_indent="yes" ;; d) directory_mode="yes" ;; r) generate_report_flag="yes" ;; h) usage; exit 0 ;; *) usage; exit 1 ;; esac done shift $((OPTIND-1)) if [ $# -eq 0 ]; then usage exit 1 fi local target="$1" # Initialize log > "$LOG_FILE" if [ "$generate_report_flag" = "yes" ]; then generate_report "$target" elif [ "$directory_mode" = "yes" ]; then format_directory "$target" "$width" elif [ -f "$target" ]; then format_file "$target" "$width" "$preserve_indent" check_line_lengths "$target" "$width" check_paragraph_structure "$target" else log "Error: $target is not a file or directory" exit 1 fi } main "$@"
Script usage output:
# Format single file: $ ./format_docs.sh document.txt [2025-12-14 17:00:00] Formatting: document.txt (width: 75) [2025-12-14 17:00:00] Success: document.txt formatted [2025-12-14 17:00:00] ✓ All lines within 75 characters (longest: 74) [2025-12-14 17:00:00] Paragraphs: 5 # Batch process directory: $ ./format_docs.sh -d -w 80 /docs [2025-12-14 17:01:00] ========================================= [2025-12-14 17:01:00] Batch formatting: /docs [2025-12-14 17:01:00] Pattern: *.txt [2025-12-14 17:01:00] Width: 80 [2025-12-14 17:01:00] ========================================= [2025-12-14 17:01:00] Formatting: intro.txt (width: 80) [2025-12-14 17:01:00] Success: intro.txt formatted [2025-12-14 17:01:00] Formatting: body.txt (width: 80) [2025-12-14 17:01:00] Success: body.txt formatted [2025-12-14 17:01:01] ========================================= [2025-12-14 17:01:01] Summary: [2025-12-14 17:01:01] Total files: 15 [2025-12-14 17:01:01] Successful: 15 [2025-12-14 17:01:01] Failed: 0 [2025-12-14 17:01:01] ========================================= # Generate report: Document Formatting Report Generated: Sun Dec 14 17:02:00 EST 2025 Directory: /docs Files Processed: ================ intro.txt 45 lines 78 max 234 words body.txt 123 lines 80 max 789 words Formatting Statistics: ===================== Total files processed: 15 Successfully formatted: 15 Failed: 0 Success rate: 100.0%
Note:

This production script handles batch processing, automatic file type detection, backup creation, quality checks, and reporting. It's suitable for formatting large documentation sets, maintaining consistent formatting standards, and automated document processing workflows.

Tips & Best Practices

Default Width is 75
fmt defaults to 75 characters, which works well for most purposes. Common alternatives: 72 for email/git, 80 for code, 100+ for documentation. Specify with -w or shorthand like fmt -80.
Use -u for Clean Spacing
Always use fmt -u for professional output. It enforces uniform spacing: one space between words, two after sentences. Makes text more readable and typographically correct.
Preserve Email Quotes with -p
For email formatting, use fmt -p '>' -w 72 to preserve quote markers. This maintains thread context while reformatting quoted text for readability.
Test Before Overwriting
Always test fmt output before overwriting files: fmt file.txt | less to preview, or fmt file.txt > file.new to create a new file. fmt doesn't modify files in-place.
Blank Lines Separate Paragraphs
fmt treats blank lines as paragraph delimiters. Each paragraph is formatted independently. Multiple blank lines are reduced to single blank lines in output.
Combine with Other Tools
fmt works great in pipelines. Use with grep to extract sections, sed to clean text, awk to process selectively. Example: grep '^#' file | fmt -w 70
Watch Out for Code and Tables
Don't fmt code or tables - it will break formatting. Use selectively on prose only. For mixed content, extract text sections with awk or grep before formatting.
Goal Width for Better Filling
Use -g flag to set goal width. fmt tries to reach goal before max width, creating more evenly filled lines. Example: fmt -w 80 -g 70
Crown Margins with -t
Use fmt -t for numbered lists and bullet points. Creates "crown margin" where first line indentation differs from continuation lines.