Linux Command Reference

pr

Synopsis

pr [OPTION]... [FILE]... pr [+PAGE] [-COLUMN] [-abcdfFmrtv] [-e[CHAR[WIDTH]]] [-h HEADER] [-i[CHAR[WIDTH]]] [-J] [-l PAGE_LENGTH] [-n[SEP[DIGITS]]] [-N LINE_NUMBER] [-o MARGIN] [-s[CHAR]] [-S[STRING]] [-w PAGE_WIDTH] [-W PAGE_WIDTH] [FILE]...

Description

The pr command formats files for printing or display, creating paginated output with headers, footers, page numbers, and multiple columns. Originally designed for preparing text files for line printers in the early Unix days, pr remains essential for creating professional-looking printed output from plain text files.

Think of pr as a bridge between raw text and formatted documents. It can convert simple text files into paginated reports with headers showing filename and page numbers, create multi-column layouts (like newspapers), add line numbers, control page length and width, merge files side-by-side, and format data for printing or terminal display. While modern word processors have replaced pr for most document creation, it remains invaluable for quick text formatting, creating printable reports from scripts, formatting code listings, and preparing text data for display or archival.

Key Concepts

Detailed Examples

Example 1

Basic Pagination with Headers

Use pr with default settings to paginate a file with headers showing filename, date/time, and page numbers. This is the most common use case for preparing files for printing.
# Create a sample file seq 1 100 | awk '{print "Line " $1 ": This is sample text"}' > sample.txt # Basic pr - adds headers and pagination pr sample.txt # View first page only pr sample.txt | head -66 # Save formatted output pr sample.txt > sample_formatted.txt # Print to default printer pr sample.txt | lpr # Display with less (better for viewing) pr sample.txt | less # See the header structure pr sample.txt | head -10 # Compare before and after echo "=== Original file (first 10 lines) ===" head -10 sample.txt echo "" echo "=== After pr (first 10 lines) ===" pr sample.txt | head -10
Output:
=== After pr (first 10 lines) === 2025-12-14 17:30 sample.txt Page 1 Line 1: This is sample text Line 2: This is sample text
Note:

pr adds a 5-line header (2 blank, header line with date/filename/page, 2 blank) and 5-line footer at bottom. Default page length is 66 lines. The header shows current date/time, centered filename, and right-aligned page number.

Example 2

Custom Headers and Page Settings

Customize headers, page length, and page width to match your printing needs or display requirements. Control how the document appears when printed or viewed.
# Custom header with -h pr -h "Monthly Sales Report" sales.txt # Disable header/footer with -t pr -t sample.txt # Set page length to 30 lines with -l pr -l 30 sample.txt # Set page width to 80 columns with -w pr -w 80 sample.txt # Combine options: custom header, shorter pages pr -h "Project Documentation" -l 40 -w 100 docs.txt # Create letterhead-style output pr -h "ACME Corporation - Internal Memo" \ -l 60 -w 80 memo.txt # Omit pagination (continuous output) with -t pr -t -w 80 continuous.txt # Set starting page number with +PAGE pr +3 sample.txt # Start from page 3 # Custom date in header (using shell) pr -h "Report - $(date +%Y-%m-%d)" data.txt # Professional report format pr -h "Quarterly Analysis - Q4 2025" \ -l 55 \ -w 85 \ -o 5 \ report.txt
Output with custom header:
2025-12-14 17:30 Monthly Sales Report Page 1 [content here] # With -t (no header/footer): Line 1: This is sample text Line 2: This is sample text [continuous content, no page breaks] # Starting from page 3: 2025-12-14 17:30 sample.txt Page 3 [content from page 3 onwards]
Note:

The -h flag sets custom header text (replaces filename). Use -t to suppress headers/footers entirely for continuous output. Page length (-l) includes header and footer. Default is 66 lines (11" paper × 6 lines/inch). Set -l 60 for actual 1-inch margins.

Example 3

Multi-Column Output

Format text in multiple columns for space-efficient printing. Perfect for lists, directories, indexes, or creating newspaper-style layouts.
# Create a list of items seq 1 50 | awk '{print "Item " $1}' > items.txt # Two columns pr -2 items.txt # Three columns pr -3 items.txt # Four columns with custom width pr -4 -w 132 items.txt # Set column separator with -s pr -2 -s"|" items.txt # Adjust spacing between columns pr -3 -s" " items.txt # Two spaces # Directory listing in columns ls -1 /usr/bin | pr -5 -t -w 100 # Create phone directory format cat > contacts.txt << 'EOF' Alice Smith - 555-0101 Bob Jones - 555-0102 Charlie Brown - 555-0103 David Wilson - 555-0104 Eve Davis - 555-0105 Frank Miller - 555-0106 EOF pr -2 -h "Contact Directory" -l 40 contacts.txt # Newspaper-style layout pr -3 -s" | " -w 120 -h "Daily News Digest" news.txt # Create index from keywords sort keywords.txt | pr -4 -t -w 100 > index.txt
Two-column output:
2025-12-14 17:30 items.txt Page 1 Item 1 Item 26 Item 2 Item 27 Item 3 Item 28 Item 4 Item 29 Item 5 Item 30 ... # Three columns with separator: Item 1 | Item 18 | Item 35 Item 2 | Item 19 | Item 36 Item 3 | Item 20 | Item 37 # Directory in 5 columns (no header with -t): file1 file26 file51 file76 file101 file2 file27 file52 file77 file102 file3 file28 file53 file78 file103
Note:

Column count specified with -NUMBER (e.g., -3 for 3 columns). pr fills columns vertically (down then across). Use -a for across filling. Default column separator is space; change with -s. Width is divided evenly among columns.

Example 4

Merging Files Side-by-Side

Use -m to merge multiple files side-by-side in columns. This is different from multi-column mode - each file occupies one column, perfect for comparisons or parallel display.
# Create comparison files cat > version1.txt << 'EOF' Function: login - Validate user - Check password - Create session - Log activity EOF cat > version2.txt << 'EOF' Function: login - Validate user - Check password hash - Create secure session - Log activity - Send notification EOF # Merge side by side pr -m -t version1.txt version2.txt # With separator pr -m -t -s" | " version1.txt version2.txt # Three files side by side pr -m -t file1.txt file2.txt file3.txt # Compare old and new with headers pr -m -h "Version Comparison" -s" || " \ old_code.c new_code.c # Merge with custom width pr -m -w 150 -s" | " left.txt right.txt # Create before/after documentation pr -m -t -h "Migration Guide" \ -s" => " \ old_syntax.txt new_syntax.txt # Side-by-side diff alternative pr -m -t -w 120 original.txt modified.txt | less # Merge multiple logs for comparison pr -m -t -s" | " \ server1.log server2.log server3.log | \ head -50 # Create bilingual document pr -m -h "English | Spanish" -s" | " \ english.txt spanish.txt
Merged output:
# With separator: Function: login | Function: login - Validate user | - Validate user - Check password | - Check password hash - Create session | - Create secure session - Log activity | - Log activity | - Send notification # Three files: File1 Line 1 File2 Line 1 File3 Line 1 File1 Line 2 File2 Line 2 File3 Line 2 File1 Line 3 File2 Line 3 File3 Line 3 # Before => After syntax: old_function() => new_function() param1 => param1, param2 return 0 => return result
Note:

The -m flag merges files horizontally, one file per column. Different from -NUMBER which splits a single file into columns. Perfect for comparisons, translations, or viewing related files together. Use -s to set separator between columns.

Example 5

Line Numbering

Add line numbers to output with -n. Essential for code listings, legal documents, or any content requiring line references. Customize numbering format and separator.
# Create sample code cat > script.sh << 'EOF' #!/bin/bash echo "Starting process..." for i in {1..10}; do echo "Processing item $i" done echo "Complete" EOF # Basic line numbering pr -n -t script.sh # Specify number width (5 digits) pr -n5 -t script.sh # Custom separator after number (: instead of tab) pr -n: -t script.sh # Line numbers with width and separator pr -n:5 -t script.sh # Numbered code listing with header pr -n -h "Script Listing" -l 60 script.sh # Start numbering from specific line with -N pr -N 100 -n -t script.sh # Number only non-blank lines (combine with awk) cat script.sh | \ awk '{if (NF) {printf "%3d %s\n", ++n, $0} else print}' | \ pr -t -h "Code Listing" # Create numbered documentation pr -n: -h "API Documentation" -l 50 api_docs.txt # Number lines in multiple columns pr -n -2 -w 100 data.txt # Professional code listing pr -n: \ -h "script.sh - Production Code" \ -l 60 \ -w 85 \ -o 5 \ script.sh
Output with line numbers:
# Basic -n: 1 #!/bin/bash 2 echo "Starting process..." 3 for i in {1..10}; do 4 echo "Processing item $i" 5 done 6 echo "Complete" # With custom separator -n:: 1:#!/bin/bash 2:echo "Starting process..." 3:for i in {1..10}; do 4: echo "Processing item $i" 5:done 6:echo "Complete" # Starting from 100 (-N 100): 100 #!/bin/bash 101 echo "Starting process..." 102 for i in {1..10}; do
Note:

The -n flag adds line numbers. Format: -n[SEP[WIDTH]] where SEP is separator (default tab) and WIDTH is number field width (default 5). Use -N to start numbering from a specific line. Great for code reviews and legal documents.

Example 6

Controlling Margins and Indentation

Adjust left margins, control indentation, and set page width to create professional layouts with proper spacing for binding or aesthetic purposes.
# Set left margin with -o (offset) pr -o 10 -t sample.txt # Large left margin for binding pr -o 15 -h "Bound Document" report.txt # Combine margin with custom width pr -o 8 -w 72 text.txt # Create indented report format pr -o 12 -h "Executive Summary" \ -l 55 -w 80 summary.txt # Professional letter format pr -o 10 \ -h "ACME Corporation" \ -l 60 \ -w 70 \ letter.txt # Set offset for hole-punch binding (3-hole) pr -o 8 -l 60 manual.txt # Tab expansion with -e cat > tabs.txt << 'EOF' Name Age City Alice 25 NYC Bob 30 LA EOF pr -t -e tabs.txt # Expand tabs to spaces # Set custom tab stops pr -t -e8 tabs.txt # Tabs every 8 spaces # Convert spaces to tabs with -i pr -t -i tabs_output.txt # Create formatted table with margins pr -o 10 -e8 -w 90 -h "Employee Directory" employees.csv # Double-spaced output with line spacing awk '{print; print ""}' text.txt | pr -o 10 -l 80
Output with offset:
# With -o 10 (10-space left margin): Line 1: This is sample text Line 2: This is sample text Line 3: This is sample text # Professional letter (-o 10 -w 70): 2025-12-14 17:30 ACME Corporation Page 1 Dear Customer, Thank you for your recent inquiry... # Tab expansion (-e8): Name Age City Alice 25 NYC Bob 30 LA
Note:

The -o flag adds left margin (offset) in spaces. Useful for binding margins or centering text on page. The -e flag expands tabs to spaces (default 8-space tabs). The -i flag does reverse (spaces to tabs). The -w flag sets total page width including margins.

Example 7

Creating Reports and Documentation

Combine pr options to create professional reports, technical documentation, and formatted output suitable for distribution or archival. Real-world report formatting examples.
# Create sales report cat > sales_data.txt << 'EOF' Q1 Sales: $125,000 Q2 Sales: $142,000 Q3 Sales: $138,000 Q4 Sales: $165,000 Total: $570,000 EOF # Professional report format pr -h "2025 Annual Sales Report" \ -l 60 \ -w 80 \ -o 10 \ sales_data.txt > sales_report.txt # Technical documentation with line numbers pr -n: \ -h "System Configuration Guide" \ -l 55 \ -w 85 \ -o 8 \ config_guide.txt # Meeting minutes pr -h "Team Meeting - $(date +%Y-%m-%d)" \ -l 50 \ -w 75 \ meeting_notes.txt # Code review document pr -n \ -h "Code Review - PR #1234" \ -l 60 \ -w 100 \ changes.diff # Multi-file report compilation { cat executive_summary.txt echo "" cat methodology.txt echo "" cat results.txt echo "" cat conclusions.txt } | pr -h "Research Report - Full Document" -l 60 -o 10 # Create comparison report pr -m -h "Q3 vs Q4 Comparison" \ -s" | " \ -w 120 \ -l 55 \ q3_data.txt q4_data.txt # Generate printable manual for file in intro.txt setup.txt usage.txt troubleshooting.txt; do pr -h "User Manual - $(basename $file .txt | tr 'a-z' 'A-Z')" \ -l 60 -o 10 -w 80 "$file" echo "" done > complete_manual.txt # Financial statement pr -h "Balance Sheet - December 2025" \ -o 15 \ -l 55 \ -w 85 \ -n: \ balance_sheet.txt # Create table of contents { echo "TABLE OF CONTENTS" echo "" find docs/ -name "*.txt" -exec basename {} \; | \ sort | nl -w3 -s". " } | pr -h "Documentation Index" -t
Professional report output:
2025-12-14 17:30 2025 Annual Sales Report Page 1 Q1 Sales: $125,000 Q2 Sales: $142,000 Q3 Sales: $138,000 Q4 Sales: $165,000 Total: $570,000 # With line numbers (technical doc): 2025-12-14 17:30 System Configuration Guide Page 1 1:Server Configuration 2:================== 3: 4:Primary Server: 192.168.1.10 5:Backup Server: 192.168.1.11
Note:

Combine multiple pr options for professional output: -h for custom headers, -o for margins, -l for page length, -w for width, -n for line numbers. Pipe multiple files through pr for consistent formatting across document sections.

Example 8

Pipeline Integration and Automation

Use pr in pipelines with other commands to create formatted output from dynamic data. Essential for automated report generation and system administration tasks.
# Format command output ps aux | pr -h "Process List - $(hostname)" -l 60 # System status report { echo "=== System Information ===" uname -a echo "" echo "=== Disk Usage ===" df -h echo "" echo "=== Memory Usage ===" free -h } | pr -h "System Status - $(date +%Y-%m-%d)" -o 5 # Format log analysis grep ERROR /var/log/syslog | \ tail -50 | \ pr -h "Recent Errors - $(date)" -n -t # Directory tree printing tree /home/user/project | pr -h "Project Structure" -t # Git log formatting git log --oneline -20 | \ pr -h "Recent Commits - $(git branch --show-current)" -t # Database query results mysql -e "SELECT * FROM users LIMIT 50" mydb | \ pr -h "User List" -t -w 120 # Network statistics netstat -tuln | \ pr -h "Active Connections" -l 40 -t # Format cron jobs crontab -l | pr -h "Scheduled Tasks - $USER" -t -n # Create backup report { echo "Backup Report - $(date)" echo "====================" echo "" find /backup -type f -mtime -1 -ls } | pr -l 60 -o 8 > backup_report.txt # Format multiple logs side by side pr -m -t -s" | " -w 150 \ <(tail -20 app.log) \ <(tail -20 error.log) \ <(tail -20 access.log) # Automated daily report cat > daily_report.sh << 'EOF' #!/bin/bash { echo "Daily System Report" echo "Generated: $(date)" echo "" echo "=== Top 10 Processes ===" ps aux --sort=-%mem | head -11 echo "" echo "=== Recent Logins ===" last -10 echo "" echo "=== Disk Usage Warnings ===" df -h | awk '$5+0 > 80 {print}' } | pr -h "Daily Report - $(hostname)" -l 60 -o 5 | \ mail -s "Daily Report" admin@example.com EOF chmod +x daily_report.sh
Pipeline output examples:
# Process list: 2025-12-14 17:30 Process List - server01 Page 1 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.1 16896 8156 ? Ss Dec13 0:02 /sbin/init # Side-by-side logs: [app.log] | [error.log] | [access.log] INFO: Starting | ERROR: Connection | 192.168.1.100 GET / DEBUG: Loading cfg | ERROR: Timeout | 192.168.1.101 POST /api INFO: Ready | WARN: Retry attempt | 192.168.1.102 GET /data # Git commits with header: Recent Commits - main a1b2c3d Fix authentication bug e4f5g6h Add new feature i7j8k9l Update documentation
Note:

pr works seamlessly in pipelines reading from stdin. Perfect for formatting command output, creating reports from scripts, or processing data streams. Use -t to suppress headers for cleaner pipeline output. Combine with process substitution for parallel file viewing.

Example 9

Advanced Formatting Tricks

Advanced pr techniques including form feeds, page breaks, across-then-down column filling, and creative combinations for specialized formatting needs.
# Fill columns across then down with -a cat > items.txt << 'EOF' Item1 Item2 Item3 Item4 Item5 Item6 EOF # Default (down then across) pr -3 -t items.txt # Across then down pr -3 -a -t items.txt # Preserve form feeds with -f cat > sections.txt << 'EOF' Section 1 content ^L Section 2 content ^L Section 3 content EOF pr -f -h "Multi-Section Document" sections.txt # Join lines with -J (no separator between columns) pr -2 -J -t file1.txt file2.txt # Omit page trailers (just header, no footer spacing) pr -F -h "Compact Format" data.txt # Double spacing effect awk '{print; print ""}' text.txt | pr -t # Landscape printing (wide format) pr -w 132 -l 40 -h "Wide Report" landscape_data.txt # Custom separator string with -S pr -2 -S"<==>" -t file1.txt file2.txt # Create columnar index sort glossary.txt | \ pr -4 -a -t -w 120 -s" " > index.txt # Format for 3-hole punch with alignment pr -o 8 -w 77 \ -h "Binder Document" \ -l 60 \ manual.txt # Create newsletter format pr -3 -s" | " \ -h "Monthly Newsletter - $(date +%B %Y)" \ -l 55 \ -w 120 \ articles.txt # Merge different file types pr -m -t -w 140 \ <(cat notes.txt) \ <(cat data.csv | column -t -s,) \ <(cat checklist.txt) # Create printer test page { echo "Printer Test Page" echo "=================" echo "" for i in {1..10}; do echo "Test line $i: The quick brown fox jumps over the lazy dog" done echo "" echo "Font samples: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" echo "Numbers: 0123456789" echo "Symbols: !@#$%^&*()_+-=[]{}|;':\"<>?,./" } | pr -h "Printer Test" -o 10 -l 60
Advanced formatting output:
# Down then across (default): Item1 Item3 Item5 Item2 Item4 Item6 # Across then down (-a): Item1 Item2 Item3 Item4 Item5 Item6 # Custom separator -S"<==>": File1 Line1<==>File2 Line1 File1 Line2<==>File2 Line2 File1 Line3<==>File2 Line3 # Newsletter format: Monthly Newsletter - December 2025 Article1 | Article2 | Article3 Text... | Text... | Text...
Note:

The -a flag fills columns across then down (like reading left-to-right). The -J flag joins lines without separators. The -F flag omits footers for denser output. The -S flag sets separator string between columns. The -f flag handles form feeds (^L) for section breaks.

Example 10

Complete Report Generation System

A comprehensive script that generates professional reports using pr with multiple formatting options, template support, and automated distribution. Production-ready for business reporting.
#!/bin/bash # File: report_generator.sh # Professional report generation system using pr set -euo pipefail # ============================================ # Configuration # ============================================ readonly REPORT_DIR="./reports" readonly TEMPLATE_DIR="./templates" readonly OUTPUT_DIR="./output" readonly DEFAULT_WIDTH=85 readonly DEFAULT_LENGTH=60 readonly DEFAULT_MARGIN=10 # ============================================ # Ensure directories exist # ============================================ mkdir -p "$REPORT_DIR" "$TEMPLATE_DIR" "$OUTPUT_DIR" # ============================================ # Logging # ============================================ log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" } # ============================================ # Template Functions # ============================================ create_header() { local title="$1" local date="${2:-$(date '+%Y-%m-%d')}" cat << EOF $title Generated: $date Company: ACME Corporation ======================================== EOF } # ============================================ # Report Formatting Functions # ============================================ format_basic_report() { local input="$1" local output="$2" local title="$3" log "Formatting basic report: $title" pr -h "$title" \ -l "$DEFAULT_LENGTH" \ -w "$DEFAULT_WIDTH" \ -o "$DEFAULT_MARGIN" \ "$input" > "$output" } format_comparison_report() { local file1="$1" local file2="$2" local output="$3" local title="$4" log "Creating comparison report: $title" pr -m \ -h "$title" \ -s" | " \ -l "$DEFAULT_LENGTH" \ -w 140 \ -o 8 \ "$file1" "$file2" > "$output" } format_code_listing() { local input="$1" local output="$2" local title="$3" log "Formatting code listing: $title" pr -n: \ -h "$title" \ -l 66 \ -w 100 \ -o 8 \ "$input" > "$output" } format_columnar_list() { local input="$1" local output="$2" local title="$3" local columns="${4:-3}" log "Creating $columns-column list: $title" pr -$columns \ -a \ -h "$title" \ -l "$DEFAULT_LENGTH" \ -w "$DEFAULT_WIDTH" \ "$input" > "$output" } format_executive_summary() { local input="$1" local output="$2" log "Formatting executive summary" { create_header "EXECUTIVE SUMMARY" echo "" cat "$input" } | pr -o 15 \ -l 55 \ -w 80 \ -t > "$output" } # ============================================ # Multi-Section Report # ============================================ compile_multi_section_report() { local report_name="$1" shift local sections=("$@") local output="$OUTPUT_DIR/${report_name}_$(date +%Y%m%d).txt" log "Compiling multi-section report: $report_name" > "$output" # Clear output file local section_num=1 for section_file in "${sections[@]}"; do local section_name=$(basename "$section_file" .txt) log " Processing section $section_num: $section_name" pr -h "Section $section_num: $section_name" \ -l "$DEFAULT_LENGTH" \ -w "$DEFAULT_WIDTH" \ -o "$DEFAULT_MARGIN" \ "$section_file" >> "$output" ((section_num++)) done log "Report compiled: $output" echo "$output" } # ============================================ # Generate Sample Data # ============================================ generate_sample_data() { log "Generating sample data..." # Sales data cat > "$REPORT_DIR/sales_q3.txt" << 'EOF' Q3 2025 Sales Summary ===================== North Region: $245,000 South Region: $189,000 East Region: $312,000 West Region: $276,000 Total Q3: $1,022,000 EOF cat > "$REPORT_DIR/sales_q4.txt" << 'EOF' Q4 2025 Sales Summary ===================== North Region: $267,000 South Region: $198,000 East Region: $334,000 West Region: $289,000 Total Q4: $1,088,000 EOF # Employee list seq 1 50 | awk '{print "Employee " $1}' > "$REPORT_DIR/employees.txt" # Meeting notes cat > "$REPORT_DIR/meeting_notes.txt" << 'EOF' Team Meeting - Strategic Planning Attendees: Management Team Duration: 2 hours Key Discussion Points: - Q4 performance exceeded expectations - New product launch scheduled for Q1 2026 - Hiring plan for expansion - Budget allocation review Action Items: - Finalize Q1 budget (Owner: Finance) - Draft product launch plan (Owner: Marketing) - Begin recruitment process (Owner: HR) EOF log "Sample data generated" } # ============================================ # Report Generation Workflows # ============================================ generate_all_reports() { log "=========================================" log "Starting report generation" log "=========================================" # Generate sample data generate_sample_data # Basic reports format_basic_report \ "$REPORT_DIR/sales_q3.txt" \ "$OUTPUT_DIR/sales_q3_formatted.txt" \ "Q3 Sales Report" format_basic_report \ "$REPORT_DIR/sales_q4.txt" \ "$OUTPUT_DIR/sales_q4_formatted.txt" \ "Q4 Sales Report" # Comparison report format_comparison_report \ "$REPORT_DIR/sales_q3.txt" \ "$REPORT_DIR/sales_q4.txt" \ "$OUTPUT_DIR/sales_comparison.txt" \ "Q3 vs Q4 Sales Comparison" # Employee list (3 columns) format_columnar_list \ "$REPORT_DIR/employees.txt" \ "$OUTPUT_DIR/employee_directory.txt" \ "Employee Directory" \ 3 # Meeting notes format_executive_summary \ "$REPORT_DIR/meeting_notes.txt" \ "$OUTPUT_DIR/meeting_summary.txt" # Compile comprehensive report local comprehensive=$(compile_multi_section_report \ "Annual_Report" \ "$REPORT_DIR/sales_q3.txt" \ "$REPORT_DIR/sales_q4.txt" \ "$REPORT_DIR/meeting_notes.txt") log "=========================================" log "Report generation complete" log "=========================================" log "Output directory: $OUTPUT_DIR" log "Files generated:" ls -lh "$OUTPUT_DIR" echo "" echo "Preview of comparison report:" head -30 "$OUTPUT_DIR/sales_comparison.txt" } # ============================================ # Main # ============================================ main() { case "${1:-generate}" in generate) generate_all_reports ;; clean) log "Cleaning output directory..." rm -rf "$OUTPUT_DIR"/* log "Clean complete" ;; *) echo "Usage: $0 {generate|clean}" exit 1 ;; esac } main "$@"
Script execution output:
[2025-12-14 17:45:00] ========================================= [2025-12-14 17:45:00] Starting report generation [2025-12-14 17:45:00] ========================================= [2025-12-14 17:45:00] Generating sample data... [2025-12-14 17:45:00] Sample data generated [2025-12-14 17:45:00] Formatting basic report: Q3 Sales Report [2025-12-14 17:45:00] Formatting basic report: Q4 Sales Report [2025-12-14 17:45:00] Creating comparison report: Q3 vs Q4 Sales... [2025-12-14 17:45:01] Creating 3-column list: Employee Directory [2025-12-14 17:45:01] Formatting executive summary [2025-12-14 17:45:01] Compiling multi-section report: Annual_Report [2025-12-14 17:45:01] Processing section 1: sales_q3 [2025-12-14 17:45:01] Processing section 2: sales_q4 [2025-12-14 17:45:01] Processing section 3: meeting_notes [2025-12-14 17:45:01] Report compiled: ./output/Annual_Report_20251214.txt [2025-12-14 17:45:01] ========================================= [2025-12-14 17:45:01] Report generation complete [2025-12-14 17:45:01] ========================================= Preview of comparison report: 2025-12-14 17:45 Q3 vs Q4 Sales Comparison Page 1 Q3 2025 Sales Summary | Q4 2025 Sales Summary ===================== | ===================== | North Region: $245,000 | North Region: $267,000 South Region: $189,000 | South Region: $198,000 East Region: $312,000 | East Region: $334,000 West Region: $276,000 | West Region: $289,000
Note:

This production system demonstrates real-world report generation with pr: multiple report types, template support, comparison views, columnar lists, multi-section compilation, and automated formatting. Perfect for business reporting, documentation generation, and automated report distribution.

Tips & Best Practices

Default Page Length is 66 Lines
Standard page is 66 lines (11 inches × 6 lines/inch). Header uses 5 lines, footer uses 5 lines, leaving 56 for content. Adjust with -l. For actual printing, use -l 60 for 1-inch margins.
Use -t for Pipeline Output
The -t flag suppresses headers and footers, creating continuous output. Essential when using pr in pipelines or when you don't want pagination. Combine with other options for formatting only.
Multi-Column vs Merge
Use -NUMBER (e.g., -3) to split one file into columns. Use -m to merge multiple files side-by-side. Different use cases: -3 for lists/indexes, -m for comparisons/translations.
Combine with lpr for Printing
Pipe pr output to lpr for direct printing: pr -h "Report" file.txt | lpr. pr formats the text, lpr sends it to printer. Perfect for quick formatted printing.
Set Margins with -o
The -o flag adds left margin (offset) in spaces. Essential for binding margins or centering on page. Common values: -o 8 for 3-hole punch, -o 10 for binding, -o 15 for professional reports.
Line Numbering Format
Use -n for line numbers. Format: -n[SEP[WIDTH]]. Example: -n:5 creates 5-digit numbers with colon separator. Great for code listings and legal documents requiring line references.
Across vs Down Column Filling
Default fills columns vertically (down then across). Use -a for horizontal filling (across then down). Choose based on how you want items ordered in multi-column output.
Width Includes Margins
Total page width (-w) includes margins (-o). If you set -w 80 -o 10, content area is 70 characters. Plan accordingly when setting dimensions for specific printers or displays.
Custom Separators Between Columns
Use -s to set column separator (default is space). For clarity, try -s" | " or -s" ". Use -S for multi-character separators. Great for making columns visually distinct.