Linux CLI 49 ๐ง pr and printf commands
cat file1.txt file2.txt
pr -m -l 10 file1.txt file2.txt
pr -3 -l 10 file1.txt
printf "My favorite number is %d and my favorite letter is %c.\n" 42 'A'
printf "Pi is approximately %.2f\n" 3.14159
printf "%b\n" "Hello, World! \n" "How are you doing\n"
pr and printf are two very different formatting tools. pr takes text and prepares it for printing โ paginating it, adding headers, arranging it into columns. printf takes a format string and data, and produces precisely formatted output โ it’s the shell’s answer to C’s printf().
Key point: pr is about layout on a page. printf is about formatting values โ numbers, strings, characters โ with exact control over width, precision, and type. printf is the more commonly used tool in scripts; pr is a legacy tool that’s still useful for column layouts.
a – pr command
pr is used to paginate or columnate files. It was designed to prepare text for line printers, but it’s still useful for arranging output into columns and adding page headers.
Syntax:
pr [options] [file...]
Common options:
| Option | Purpose |
|---|---|
-m | Print files side by side (merge) |
-l N | Set page length to N lines |
-N | Format output in N columns |
-h HEADER | Use HEADER as the page header |
-t | Omit page headers and footers |
-d | Double-space the output |
-n | Number lines |
-w N | Set page width to N columns |
-F | Use form feeds between pages |
-s CHAR | Use CHAR as the column separator |
Examples:
# Look at the files
$ cat file1.txt
one
two
three
four
five
$ cat file2.txt
alpha
beta
gamma
delta
epsilon
# Print files side by side
$ pr -m -l 10 file1.txt file2.txt
2024-01-15 10:00 Page 1
one alpha
two beta
three gamma
four delta
five epsilon
# Without headers, side by side
$ pr -m -t file1.txt file2.txt
one alpha
two beta
three gamma
four delta
five epsilon
# Format a single file into 3 columns
$ pr -3 -l 10 file1.txt
2024-01-15 10:00 Page 1
one two three
four five
# With -t (no headers)
$ pr -3 -t file1.txt
one two three
four five
# Number lines
$ pr -n -t file1.txt
1 one
2 two
3 three
4 four
5 five
# Double-space
$ pr -d -t file1.txt
one
two
three
four
five
# Custom header
$ pr -h "My Report" file1.txt
2024-01-15 10:00 My Report Page 1
one
two
three
four
five
# Custom column separator
$ pr -m -t -s ' | ' file1.txt file2.txt
one | alpha
two | beta
three | gamma
four | delta
five | epsilon
Understanding the output:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Default pr output โ
โ โ
โ (blank line) โ
โ (blank line) โ
โ 2024-01-15 10:00 Page 1 โ
โ โ
โ (blank line) โ
โ (blank line) โ
โ one โ
โ two โ
โ three โ
โ โ
โ (blank lines at end) โ
โ โ
โ Header: date + page number โ
โ Footer: blank lines โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Use -t to suppress the headers and footers โ that’s what you want most of the time when using pr in a pipeline.
Multi-column formatting:
# Two columns
$ pr -2 -t file1.txt
one four
two five
three
# Three columns
$ pr -3 -t file1.txt
one two three
four five
# Four columns
$ pr -4 -t file1.txt
one two three four
five
pr vs paste:
| Tool | Effect |
|---|---|
pr -m | Merges files side by side (like paste but with page formatting) |
paste | Merges files side by side (TAB-separated, no page formatting) |
pr -N | Splits one file into N columns |
column | Formats into columns (more flexible, not always installed) |
Note:
pris a legacy tool. For most modern uses,paste,column, orawkdo a better job. Butpr -m -tis a quick way to merge files side by side with a wider separator thanpaste‘s TAB.
b – printf command
printf is used to format and print data to the screen. It can display strings, integers, floating-point numbers, and characters. It’s the shell’s equivalent of C’s printf() โ and it’s one of the most useful tools in scripting.
Syntax:
printf FORMAT [ARGUMENTS...]
Common format specifiers:
| Specifier | Purpose |
|---|---|
%s | Print a string |
%d | Print a decimal integer |
%f | Print a floating-point number |
%x | Print a hexadecimal number |
%o | Print an octal number |
%c | Print a single character |
%e | Print in scientific notation |
%% | Print a literal % |
Width and precision:
| Format | Meaning |
|---|---|
%5d | Right-align in 5 columns |
%-5d | Left-align in 5 columns |
%05d | Zero-pad to 5 digits |
%.2f | 2 decimal places |
%8.2f | Width 8, 2 decimals |
%10s | Right-align string in 10 columns |
%-10s | Left-align string in 10 columns |
Escape sequences:
| Escape | Meaning |
|---|---|
\n | Newline |
\t | Tab |
\\ | Backslash |
\a | Alert (bell) |
\r | Carriage return |
\b | Backspace |
\0NNN | Octal character |
\xHH | Hex character |
Examples:
# Basic string and number substitution
$ printf "My favorite number is %d and my favorite letter is %c.\n" 42 'A'
My favorite number is 42 and my favorite letter is A.
# Floating-point with precision
$ printf "Pi is approximately %.2f\n" 3.14159
Pi is approximately 3.14
# %b โ interpret escape sequences in the argument
$ printf "%b\n" "Hello, World! \n" "How are you doing\n"
Hello, World!
How are you doing
# String formatting
$ printf "Name: %s, Age: %d\n" "Alice" 30
Name: Alice, Age: 30
# Multiple arguments โ the format repeats
$ printf "%s\n" one two three four
one
two
three
four
# Width and alignment
$ printf "|%10s|%-10s|\n" "right" "left"
| right|left |
# Zero-padding
$ printf "%05d\n" 42
00042
# Hexadecimal and octal
$ printf "%x %o\n" 255 8
ff 10
# Scientific notation
$ printf "%e\n" 1234567
1.234567e+06
# Multiple specifiers
$ printf "%-10s %5d %8.2f\n" "apple" 5 1.234
apple 5 1.23
# Table-like output
$ printf "%-15s %-10s %5s\n" "Name" "Dept" "Score"
$ printf "%-15s %-10s %5d\n" "Alice" "Eng" 95
$ printf "%-15s %-10s %5d\n" "Bob" "Math" 87
Name Dept Score
Alice Eng 95
Bob Math 87
# Literal percent sign
$ printf "100%% complete\n"
100% complete
# Escape sequences
$ printf "Line 1\nLine 2\nLine 3\n"
Line 1
Line 2
Line 3
# Tabs
$ printf "col1\tcol2\tcol3\n"
col1 col2 col3
# Alert/bell
$ printf "Done\a\n"
# Character from code
$ printf "\x41\n"
A
# Reuse format with multiple arguments
$ printf "%d\n" 1 2 3 4 5
1
2
3
4
5
# Format cycles if more args than specifiers
$ printf "%s: %d\n" a 1 b 2 c 3
a: 1
b: 2
c: 3
printf vs echo:
| Aspect | printf | echo |
|---|---|---|
| Formatting | Full control | Limited |
| Portability | POSIX-standard | Shell-dependent |
| Escape handling | Explicit | Varies (-e in bash) |
| Newline | Only if you add \n | Added by default |
| Numbers | Format with precision | Just prints |
| Best for | Scripts, tables, reports | Quick messages |
# echo adds a newline by default
$ echo "hello"
hello
# printf does NOT โ you must add \n
$ printf "hello"
hello$
# With \n
$ printf "hello\n"
hello
Building a table with printf:
$ printf "%-15s %-10s %s\n" "NAME" "DEPT" "SCORE"
$ printf "%-15s %-10s %d\n" "Alice" "Eng" 95
$ printf "%-15s %-10s %d\n" "Bob" "Math" 87
$ printf "%-15s %-10s %d\n" "Charlie" "Sci" 92
NAME DEPT SCORE
Alice Eng 95
Bob Math 87
Charlie Sci 92
Formatting numbers in a loop:
$ for i in 1 2 3 4 5; do
printf "Item %03d: %s\n" "$i" "processed"
done
Item 001: processed
Item 002: processed
Item 003: processed
Item 004: processed
Item 005: processed
Converting between number bases:
$ printf "Decimal: %d, Hex: %x, Octal: %o\n" 255 255 255
Decimal: 255, Hex: ff, Octal: 377
Printing a character from its ASCII code:
$ printf "ASCII 65 = %c\n" 65
ASCII 65 = A
$ printf "\x48\x65\x6c\x6c\x6f\n"
Hello
Using %b for escape sequences in arguments:
$ printf "%b\n" "Line 1\nLine 2"
Line 1
Line 2
$ printf "%s\n" "Line 1\nLine 2"
Line 1\nLine 2
# %s treats the argument literally
Difference between %s and %b:
| Specifier | Behavior |
|---|---|
%s | Prints the string literally โ no escape processing |
%b | Processes \n, \t, etc. in the argument |
$ printf "%s\n" "Hello\nWorld"
Hello\nWorld
$ printf "%b\n" "Hello\nWorld"
Hello
World
โ ๏ธ Warning: Unlike
echo,printfrequires a format string. If you pass a variable that starts with-or contains%, things can break. Always useprintf '%s\n' "$var"when you just want to print a variable safely:$ var="100% done" $ printf "$var\n" # โ % is a format specifier $ printf '%s\n' "$var" # โ safe
Complete Example Session
# ============================================
# PART 1: PR โ MERGE FILES SIDE BY SIDE
# ============================================
$ cat file1.txt
one
two
three
four
five
$ cat file2.txt
alpha
beta
gamma
delta
epsilon
$ pr -m -l 10 file1.txt file2.txt
2024-01-15 10:00 Page 1
one alpha
two beta
three gamma
four delta
five epsilon
# Without headers
$ pr -m -t file1.txt file2.txt
one alpha
two beta
three gamma
four delta
five epsilon
# ============================================
# PART 2: PR โ COLUMNATE A SINGLE FILE
# ============================================
$ pr -3 -l 10 file1.txt
2024-01-15 10:00 Page 1
one two three
four five
$ pr -3 -t file1.txt
one two three
four five
# ============================================
# PART 3: PR โ NUMBER LINES
# ============================================
$ pr -n -t file1.txt
1 one
2 two
3 three
4 four
5 five
# ============================================
# PART 4: PR โ CUSTOM HEADER
# ============================================
$ pr -h "My Report" file1.txt
2024-01-15 10:00 My Report Page 1
one
two
three
four
five
# ============================================
# PART 5: PRINTF โ BASIC FORMATTING
# ============================================
$ printf "My favorite number is %d and my favorite letter is %c.\n" 42 'A'
My favorite number is 42 and my favorite letter is A.
$ printf "Pi is approximately %.2f\n" 3.14159
Pi is approximately 3.14
$ printf "%b\n" "Hello, World! \n" "How are you doing\n"
Hello, World!
How are you doing
# ============================================
# PART 6: PRINTF โ WIDTH AND ALIGNMENT
# ============================================
$ printf "|%10s|%-10s|\n" "right" "left"
| right|left |
$ printf "%05d\n" 42
00042
$ printf "%-15s %-10s %5s\n" "Name" "Dept" "Score"
$ printf "%-15s %-10s %5d\n" "Alice" "Eng" 95
$ printf "%-15s %-10s %5d\n" "Bob" "Math" 87
Name Dept Score
Alice Eng 95
Bob Math 87
# ============================================
# PART 7: PRINTF โ NUMBER BASES
# ============================================
$ printf "Decimal: %d, Hex: %x, Octal: %o\n" 255 255 255
Decimal: 255, Hex: ff, Octal: 377
$ printf "%e\n" 1234567
1.234567e+06
# ============================================
# PART 8: PRINTF โ ESCAPE SEQUENCES
# ============================================
$ printf "Line 1\nLine 2\nLine 3\n"
Line 1
Line 2
Line 3
$ printf "col1\tcol2\tcol3\n"
col1 col2 col3
$ printf "\x48\x65\x6c\x6c\x6f\n"
Hello
# ============================================
# PART 9: PRINTF โ CYCLING FORMAT
# ============================================
$ printf "%d\n" 1 2 3 4 5
1
2
3
4
5
$ printf "%s: %d\n" a 1 b 2 c 3
a: 1
b: 2
c: 3
# ============================================
# PART 10: PRINTF โ %s vs %b
# ============================================
$ printf "%s\n" "Hello\nWorld"
Hello\nWorld
$ printf "%b\n" "Hello\nWorld"
Hello
World
# ============================================
# PART 11: COMBINING PR AND PRINTF
# ============================================
# Generate a report with printf
$ printf "%-10s %5s\n" "Alice" 95
$ printf "%-10s %5s\n" "Bob" 87
Alice 95
Bob 87
# Columnate a list with pr
$ ls | pr -3 -t
docs notes.txt todo.txt
readme.md scripts work
# ============================================
# PART 12: REAL-WORLD USES
# ============================================
# Numbered list in a script
$ for f in *.txt; do
printf "%3d: %s\n" $((i++)) "$f"
done
1: file1.txt
2: file2.txt
3: file3.txt
# Tabular report
$ printf "%-20s %-15s %s\n" "USER" "SHELL" "HOME"
$ while IFS=: read -r user _ _ _ _ home shell; do
printf "%-20s %-15s %s\n" "$user" "$shell" "$home"
done < /etc/passwd | head -5
USER SHELL HOME
root /bin/bash /root
daemon /usr/sbin/nologin /usr/sbin
bin /usr/sbin/nologin /bin
sys /usr/sbin/nologin /dev
sync /bin/sync /bin
# Progress with zero-padded numbers
$ for i in $(seq 1 100); do
printf "\rProcessing: %03d/100" "$i"
sleep 0.01
done
echo
Processing: 100/100
Quick Reference
pr
| Command | Purpose |
|---|---|
pr FILE | Format with headers |
pr -t FILE | No headers |
pr -m A B | Merge side by side |
pr -m -t A B | Merge without headers |
pr -N -t FILE | N columns |
pr -l N FILE | Page length N |
pr -h HEADER FILE | Custom header |
pr -n FILE | Number lines |
pr -d FILE | Double-space |
pr -s CHAR A B | Column separator |
pr -w N FILE | Page width |
printf โ Specifiers
| Specifier | Purpose |
|---|---|
%s | String |
%d | Decimal integer |
%f | Float |
%x | Hex |
%o | Octal |
%c | Character |
%e | Scientific |
%% | Literal % |
%b | String with escapes |
printf โ Width/Precision
| Format | Meaning |
|---|---|
%5d | Right-align width 5 |
%-5d | Left-align width 5 |
%05d | Zero-pad to 5 |
%.2f | 2 decimals |
%8.2f | Width 8, 2 decimals |
%10s | Right-align string |
%-10s | Left-align string |
printf โ Escapes
| Escape | Meaning |
|---|---|
\n | Newline |
\t | Tab |
\\ | Backslash |
\a | Bell |
\r | Carriage return |
\b | Backspace |
\xHH | Hex char |
\0NNN | Octal char |
printf vs echo
| Aspect | printf | echo |
|---|---|---|
| Format control | Full | Limited |
| Escape handling | Explicit | -e in bash |
| Newline | Manual \n | Automatic |
| Portability | POSIX | Shell-dependent |
| Numbers | Full formatting | Plain |
Best Practices
โ Do This:
# Use -t with pr for pipeline-friendly output
pr -m -t file1 file2 # โ
# Use printf for tables
printf "%-15s %5s\n" "Name" "Score" # โ
# Use %s when printing variables safely
printf '%s\n' "$var" # โ
# Add \n explicitly with printf
printf "hello\n" # โ
# Use width specifiers for alignment
printf "%05d\n" 42 # โ
# Use %b when you want escape handling
printf "%b\n" "line1\nline2" # โ
# Use printf in scripts instead of echo
printf "Error: %s\n" "$msg" >&2 # โ
โ Don’t Do This:
# Don't forget \n with printf
printf "hello" # โ no newline
# Don't pass user input as the format string
printf "$user_input" # โ format injection
# Don't use pr without -t in pipelines
pr file1 file2 | grep foo # โ headers pollute
# Don't use echo -e in portable scripts
echo -e "line1\nline2" # โ not POSIX
# Don't rely on echo's behavior for escapes
echo "line1\nline2" # โ shell-dependent
# Don't forget width for alignment
printf "%s %s\n" "a" "b" # โ ๏ธ no alignment
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
printf no newline | Output runs together | Add \n |
% in variable | Format injection | Use printf '%s' "$var" |
pr headers in output | Pollutes pipelines | Use -t |
%s vs %b | Escapes not processed | Use %b when needed |
| Missing arguments | Empty output | Match args to specifiers |
| Wrong width | Misaligned columns | Use %-Ns consistently |
echo -e | Not portable | Use printf |
| Locale decimals | Comma vs dot | Set LC_ALL=C |
Real-World Examples
1. Merge Two Files Side by Side
$ pr -m -t names.txt scores.txt
alice 95
bob 87
charlie 92
2. Print in Three Columns
$ pr -3 -t file1.txt
one two three
four five
3. Custom Page Header
$ pr -h "Monthly Report" data.txt > report.txt
4. Format a Number with Leading Zeros
$ printf "%05d\n" 42
00042
5. Print Pi with Precision
$ printf "Pi is approximately %.2f\n" 3.14159
Pi is approximately 3.14
6. Build a Table
$ printf "%-15s %-10s %5s\n" "NAME" "DEPT" "SCORE"
$ printf "%-15s %-10s %5d\n" "Alice" "Eng" 95
$ printf "%-15s %-10s %5d\n" "Bob" "Math" 87
NAME DEPT SCORE
Alice Eng 95
Bob Math 87
7. Convert to Hex
$ printf "0x%x\n" 255
0xff
8. Print with Escape Sequences
$ printf "Line 1\nLine 2\nLine 3\n"
Line 1
Line 2
Line 3
9. Print a Character from ASCII
$ printf "ASCII 65 = %c\n" 65
ASCII 65 = A
10. Cycle Format with Arguments
$ printf "%s: %d\n" a 1 b 2 c 3
a: 1
b: 2
c: 3
11. Progress Bar with \r
$ for i in $(seq 1 100); do
printf "\rProgress: %3d%%" "$i"
sleep 0.01
done
echo
Progress: 100%
12. Number Files in a Loop
$ i=1
$ for f in *.txt; do
printf "%3d: %s\n" $i "$f"
i=$((i+1))
done
1: file1.txt
2: file2.txt
3: file3.txt
13. Columnate ls Output
$ ls | pr -3 -t
docs notes.txt todo.txt
readme.md scripts work
14. Safe Variable Printing
$ var="100% done"
$ printf '%s\n' "$var"
100% done
15. Error Messages in Scripts
$ printf "Error: %s (code %d)\n" "File not found" 2 >&2
Error: File not found (code 2)
16. Format a Date
$ printf "Year: %d, Month: %02d, Day: %02d\n" 2024 1 15
Year: 2024, Month: 01, Day: 15
17. Right-Align a Column of Numbers
$ for n in 5 100 42 1000 7; do
printf "%6d\n" "$n"
done
5
100
42
1000
7
18. Side-by-Side Comparison
$ paste <(printf "%-10s\n" old1 old2 old3) \
<(printf "%-10s\n" new1 new2 new3)
old1 new1
old2 new2
old3 new3
Visual: pr and printf
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ pr -m -t โ
โ โ
โ file1: file2: output: โ
โ one alpha one alpha โ
โ two beta two beta โ
โ three gamma three gamma โ
โ โ
โ Merges side by side (no headers) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ pr -3 -t โ
โ โ
โ file: output: โ
โ one one two three โ
โ two four five โ
โ three โ
โ four โ
โ five โ
โ โ
โ Splits into columns โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ printf "%-10s %5d\n" โ
โ โ
โ Format: %-10s %5d โ
โ โ โ โ
โ โ โโ right-align 5 wide โ
โ โโโโโโโโโโโ left-align 10 wide โ
โ โ
โ Args: "apple" 5 โ
โ Output: apple 5 โ
โ โ
โ Exact control over every character โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Command | Purpose | Example |
|---|---|---|
pr FILE | Format with headers | pr file1.txt |
pr -t FILE | No headers | pr -t file1.txt |
pr -m -t A B | Merge side by side | pr -m -t file1.txt file2.txt |
pr -3 -t FILE | 3 columns | pr -3 -t file1.txt |
pr -l N FILE | Page length N | pr -l 10 file1.txt |
pr -h H FILE | Custom header | pr -h "Report" file1.txt |
pr -n FILE | Number lines | pr -n file1.txt |
printf "%d" N | Integer | printf "%d\n" 42 |
printf "%s" S | String | printf "%s\n" "hello" |
printf "%f" N | Float | printf "%f\n" 3.14 |
printf "%.2f" N | 2 decimals | printf "%.2f\n" 3.14159 |
printf "%c" N | Character | printf "%c\n" 65 |
printf "%x" N | Hex | printf "%x\n" 255 |
printf "%o" N | Octal | printf "%o\n" 8 |
printf "%e" N | Scientific | printf "%e\n" 1234567 |
printf "%-Ns" S | Left-align | printf "%-10s\n" "x" |
printf "%Nd" N | Right-align | printf "%5d\n" 42 |
printf "%0Nd" N | Zero-pad | printf "%05d\n" 42 |
printf "%b" S | Escapes in arg | printf "%b\n" "a\nb" |
printf "%%" | Literal % | printf "100%%\n" |
Key takeaways:
prpaginates and columnates โ use-tto suppress headers in pipelinespr -m -t A Bmerges two files side by sidepr -N -t FILEsplits one file into N columnsprintfgives you precise control over output format โ it’s the scripting standard%sfor strings,%dfor integers,%ffor floats,%cfor characters,%x/%ofor other bases- Use
%.2ffor decimal precision,%05dfor zero-padding,%-10sfor left-alignment printfdoes not add a newline โ include\nexplicitly%binterprets escape sequences in the argument;%sprints literally- Prefer
printfoverechoin scripts โ it’s portable, predictable, and powerful - Use
printf '%s\n' "$var"to safely print variables that might contain%or-
Remember: pr is a layout tool โ use it when you want columns or a printable page. printf is a formatting engine โ use it whenever you need exact control over how values appear. In scripts, printf replaces both echo and awk‘s formatted printing for most cases. Learn the width and precision specifiers, and you can build clean tables, progress bars, and reports in a single line. And always quote variables when passing them to printf โ or you’ll get format surprises.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!