Linux CLI 45 🐧patch and tr commands
echo "[section1] key1=value1 key2=value2" > config_v1.ini
echo "[section1] key1=new_value1 new_key=new_value" > config_v2.ini
diff -u config_v1.ini config_v2.ini > config_patch.diff
patch config_v1.ini < config_patch.diff
echo "hello" | tr 'e' 'E'
echo "hello world" | tr 'lo' 'LO'
echo "hello world" | tr -d 'lo'
echo "HELLO WORLD" | tr 'A-Z' 'a-z'
patch and tr sit at opposite ends of the text-processing spectrum. patch applies a diff file to an original — it’s how software updates and bug fixes are distributed. tr translates or deletes individual characters from a stream — it’s the simplest character-level filter on Linux.
Key point: patch works together with diff. diff produces the description of a change; patch applies it. tr works on single characters only — it can’t match words or patterns. For those, you need sed or awk.
a – patch command
patch is used to apply a diff file to an original source. It is useful for applying bug fixes and updating software source. The workflow is: compare the old and new versions with diff, save the output to a patch file, then apply that patch to the original.
Syntax:
patch [options] original-file < patch-file
Common options:
| Option | Purpose |
|---|---|
-b | Make a backup file (.orig) |
-c | Interpret the patch as a context diff |
-f | Force — assume the patch is not reversed |
-R | Reverse the patch (undo it) |
-p N | Strip N leading path components |
-i FILE | Read the patch from FILE instead of stdin |
-d DIR | Change to DIR first |
--dry-run | Show what would happen without applying |
The workflow:
# 1. Create the original file
$ echo "[section1] key1=value1 key2=value2" > config_v1.ini
$ cat config_v1.ini
[section1] key1=value1 key2=value2
# 2. Create the modified version
$ echo "[section1] key1=new_value1 new_key=new_value" > config_v2.ini
$ cat config_v2.ini
[section1] key1=new_value1 new_key=new_value
# 3. Compare and save the difference as a patch
$ diff -u config_v1.ini config_v2.ini > config_patch.diff
$ cat config_patch.diff
--- config_v1.ini 2024-01-15 10:00:00.000000000 +0000
+++ config_v2.ini 2024-01-15 10:05:00.000000000 +0000
@@ -1 +1 @@
-[section1] key1=value1 key2=value2
+[section1] key1=new_value1 new_key=new_value
# 4. Apply the patch to the original
$ patch config_v1.ini < config_patch.diff
patching file config_v1.ini
# 5. Verify — the files now match
$ diff config_v1.ini config_v2.ini
# (no output = identical)
$ cat config_v1.ini
[section1] key1=new_value1 new_key=new_value
How it works:
┌──────────────────────────────────────────────┐
│ The patch workflow │
│ │
│ config_v1.ini ─┐ │
│ ├──► diff -u ──► .diff │
│ config_v2.ini ─┘ │
│ │
│ Then: │
│ │
│ config_v1.ini ──► patch < .diff ──► patched│
│ │
│ The patch contains only the CHANGES, │
│ not the whole file — small and efficient. │
│ │
└──────────────────────────────────────────────┘
More examples:
# Make a backup before patching
$ patch -b config_v1.ini < config_patch.diff
patching file config_v1.ini
# config_v1.ini.orig is created
# Dry run — see what would happen
$ patch --dry-run config_v1.ini < config_patch.diff
checking file config_v1.ini
# Reverse a patch (undo it)
$ patch -R config_v1.ini < config_patch.diff
patching file config_v1.ini
# Use a context diff instead of unified
$ diff -c config_v1.ini config_v2.ini > config_patch.diff
$ patch config_v1.ini < config_patch.diff
# Patch with -p1 (strip one path component)
$ patch -p1 < fix.patch
# Patch all files in a directory
$ cd project/
$ patch -p1 < ../fix.patch
# Patch from a file instead of stdin
$ patch -i config_patch.diff config_v1.ini
# Patch a whole tree
$ patch -p1 -d /path/to/source < fix.patch
# Force apply
$ patch -f config_v1.ini < config_patch.diff
# See what files a patch affects
$ patch --dry-run -p1 < fix.patch
Why -p1 matters:
Patches generated by git diff or diff -u often include a leading path like a/src/file.c and b/src/file.c. The -p1 flag strips the first component (a/ or b/), so the patch applies cleanly to src/file.c:
# Typical git patch header
--- a/src/main.c
+++ b/src/main.c
# Apply with -p1 to strip the "a/" and "b/"
$ patch -p1 < fix.patch
Common patch levels:
| Flag | Strips | Example path becomes |
|---|---|---|
-p0 | Nothing | a/src/main.c |
-p1 | 1 component | src/main.c |
-p2 | 2 components | main.c |
Tip: If a patch fails,
patchcreates a.rejfile with the rejected hunks. Inspect it, fix manually, and re-run. Look for.orig(from-b) and.rejfiles after a failure.
Fixing a failed patch:
$ patch -p1 < fix.patch
patching file src/main.c
Hunk #1 FAILED at 42.
1 out of 1 hunk FAILED -- saving rejects to file src/main.c.rej
# The .rej file contains the hunk that couldn't apply
$ cat src/main.c.rej
--- src/main.c
+++ src/main.c
@@ -42,7 +42,7 @@
- old_function();
+ new_function();
# Edit the file manually, apply the change, and remove the .rej
$ nano src/main.c
$ rm src/main.c.rej
b – tr command
tr is used to delete or translate characters. It reads from standard input and writes to standard output. It performs character replacements according to a mapping defined by its arguments.
Syntax:
tr [options] SET1 [SET2]
| Option | Purpose |
|---|---|
-d | Delete characters in SET1 |
-s | Squeeze repeated characters into one |
-c | Use the complement of SET1 |
-t | Truncate SET1 to the length of SET2 |
How it works: tr maps each character in SET1 to the corresponding character in SET2, position by position. If SET1 is longer than SET2, the last character of SET2 is repeated.
Basic examples:
# Change 'e' to 'E'
$ echo "hello" | tr 'e' 'E'
hEllo
# Change 'l' to 'L' and 'o' to 'O'
$ echo "hello world" | tr 'lo' 'LO'
heLLO wOrLd
# Delete 'l' and 'o'
$ echo "hello world" | tr -d 'lo'
he wrd
# Change all uppercase to lowercase
$ echo "HELLO WORLD" | tr 'A-Z' 'a-z'
hello world
Ranges and character classes:
# Uppercase to lowercase
$ echo "HELLO" | tr 'A-Z' 'a-z'
hello
# Lowercase to uppercase
$ echo "hello" | tr 'a-z' 'A-Z'
HELLO
# Digits to a placeholder
$ echo "call 555-1234" | tr '0-9' '#'
call ###-####
# ROT13 (classic cipher)
$ echo "hello" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
uryyb
POSIX classes in tr:
| Class | Matches |
|---|---|
[:alnum:] | Letters and digits |
[:alpha:] | Letters |
[:digit:] | Digits |
[:lower:] | Lowercase |
[:upper:] | Uppercase |
[:space:] | Whitespace |
[:punct:] | Punctuation |
# Uppercase to lowercase using classes
$ echo "HELLO" | tr '[:upper:]' '[:lower:]'
hello
# Lowercase to uppercase
$ echo "hello" | tr '[:lower:]' '[:upper:]'
HELLO
# Delete all digits
$ echo "abc123def456" | tr -d '[:digit:]'
abcdef
# Delete all punctuation
$ echo "hello, world!" | tr -d '[:punct:]'
hello world
# Replace whitespace with newline
$ echo "a b c d" | tr ' ' '\n'
a
b
c
d
Squeeze mode (-s):
# Collapse multiple spaces into one
$ echo "hello world" | tr -s ' '
hello world
# Collapse repeated newlines
$ printf "a\n\n\nb\n\nc\n" | tr -s '\n'
a
b
c
# Collapse repeated characters
$ echo "aaabbbccc" | tr -s 'abc'
abc
Complement mode (-c):
# Delete everything EXCEPT digits
$ echo "abc123def456" | tr -cd '[:digit:]'
123456
# Delete everything except letters and newlines
$ echo "hello123world!" | tr -cd '[:alpha:]\n'
helloworld
# Replace everything except digits with a space
$ echo "abc123def" | tr -c '[:digit:]' ' '
123
Common special characters:
| Escape | Meaning |
|---|---|
\n | Newline |
\t | Tab |
\r | Carriage return |
\\ | Backslash |
\0 | Null |
# Convert newlines to spaces
$ printf "a\nb\nc\n" | tr '\n' ' '
a b c
# Convert spaces to newlines (one word per line)
$ echo "a b c d" | tr ' ' '\n'
a
b
c
d
# Remove carriage returns (Windows line endings)
$ tr -d '\r' < windows.txt > unix.txt
# Convert tabs to spaces
$ tr '\t' ' ' < file.txt
# Delete all non-printable characters
$ tr -cd '[:print:]\n' < file.txt
Important:
tris not a word-replacer.tr 'lo' 'LO'doesn’t replace the word “lo” — it replaces everylwithLand everyowithO. For word replacement, usesed 's/lo/LO/g'.
tr vs sed:
| Aspect | tr | sed |
|---|---|---|
| Works on | Single characters | Patterns/lines |
| Can delete chars | Yes (-d) | Yes (s///) |
| Can squeeze | Yes (-s) | With regex |
| Can translate | Yes | With y/// |
| Use case | Character-level filters | Pattern/word replacement |
Complete Example Session
# ============================================
# PART 1: CREATE THE ORIGINAL AND NEW FILES
# ============================================
$ echo "[section1] key1=value1 key2=value2" > config_v1.ini
$ cat config_v1.ini
[section1] key1=value1 key2=value2
$ echo "[section1] key1=new_value1 new_key=new_value" > config_v2.ini
$ cat config_v2.ini
[section1] key1=new_value1 new_key=new_value
# ============================================
# PART 2: CREATE THE PATCH
# ============================================
$ diff -u config_v1.ini config_v2.ini > config_patch.diff
$ cat config_patch.diff
--- config_v1.ini 2024-01-15 10:00:00.000000000 +0000
+++ config_v2.ini 2024-01-15 10:05:00.000000000 +0000
@@ -1 +1 @@
-[section1] key1=value1 key2=value2
+[section1] key1=new_value1 new_key=new_value
# ============================================
# PART 3: APPLY THE PATCH
# ============================================
$ patch config_v1.ini < config_patch.diff
patching file config_v1.ini
$ cat config_v1.ini
[section1] key1=new_value1 new_key=new_value
$ diff config_v1.ini config_v2.ini
# (no output = identical)
# ============================================
# PART 4: PATCH WITH BACKUP
# ============================================
$ echo "original" > file.txt
$ echo "modified" > file.new
$ diff -u file.txt file.new > file.patch
$ patch -b file.txt < file.patch
patching file file.txt
$ ls file.txt*
file.txt file.txt.orig
$ cat file.txt.orig
original
# ============================================
# PART 5: REVERSE A PATCH
# ============================================
$ patch -R file.txt < file.patch
patching file file.txt
$ cat file.txt
original
# ============================================
# PART 6: TR — TRANSLATE
# ============================================
$ echo "hello" | tr 'e' 'E'
hEllo
$ echo "hello world" | tr 'lo' 'LO'
heLLO wOrLd
# ============================================
# PART 7: TR — DELETE
# ============================================
$ echo "hello world" | tr -d 'lo'
he wrd
$ echo "abc123def456" | tr -d '[:digit:]'
abcdef
# ============================================
# PART 8: TR — CASE CONVERSION
# ============================================
$ echo "HELLO WORLD" | tr 'A-Z' 'a-z'
hello world
$ echo "hello world" | tr 'a-z' 'A-Z'
HELLO WORLD
$ echo "HELLO" | tr '[:upper:]' '[:lower:]'
hello
# ============================================
# PART 9: TR — SQUEEZE
# ============================================
$ echo "hello world" | tr -s ' '
hello world
$ echo "aaabbbccc" | tr -s 'abc'
abc
# ============================================
# PART 10: TR — COMPLEMENT
# ============================================
$ echo "abc123def456" | tr -cd '[:digit:]'
123456
$ echo "hello123world!" | tr -cd '[:alpha:]\n'
helloworld
# ============================================
# PART 11: TR — NEWLINES AND SPACES
# ============================================
# Newline to space
$ printf "a\nb\nc\n" | tr '\n' ' '
a b c
# Space to newline
$ echo "a b c d" | tr ' ' '\n'
a
b
c
d
# Remove carriage returns (Windows → Unix)
$ tr -d '\r' < windows.txt > unix.txt
# ============================================
# PART 12: COMBINING TR WITH OTHER TOOLS
# ============================================
# Word frequency count
$ cat book.txt | tr -s '[:space:]' '\n' | sort | uniq -c | sort -rn | head -10
# Clean a list of emails
$ cat emails.txt | tr 'A-Z' 'a-z' | sort -u
# One word per line
$ echo "the quick brown fox" | tr ' ' '\n'
the
quick
brown
fox
Quick Reference
patch
| Command | Purpose |
|---|---|
patch FILE < patch.diff | Apply a patch |
patch -b FILE < patch.diff | Apply with backup |
patch -R FILE < patch.diff | Reverse a patch |
patch -p1 < patch.diff | Strip one path component |
patch -p0 < patch.diff | No stripping |
patch -p2 < patch.diff | Strip two components |
patch --dry-run < patch.diff | Preview only |
patch -i patch.diff FILE | Read patch from file |
patch -d DIR < patch.diff | Change directory first |
patch -f FILE < patch.diff | Force apply |
patch -c FILE < patch.diff | Context diff format |
tr
| Command | Purpose |
|---|---|
tr 'a' 'b' | Replace a with b |
tr 'abc' 'xyz' | Map a→x, b→y, c→z |
tr 'A-Z' 'a-z' | Uppercase to lowercase |
tr 'a-z' 'A-Z' | Lowercase to uppercase |
tr -d 'SET' | Delete characters |
tr -s 'SET' | Squeeze repeats |
tr -c 'SET' | Complement |
tr -cd 'SET' | Delete complement |
tr '[:upper:]' '[:lower:]' | Case using classes |
tr '\n' ' ' | Newline to space |
tr ' ' '\n' | Space to newline |
tr -d '\r' | Remove CR |
tr -s '[:space:]' | Squeeze whitespace |
tr — Character Classes
| Class | Matches |
|---|---|
[:alnum:] | Letters + digits |
[:alpha:] | Letters |
[:digit:] | Digits |
[:lower:] | Lowercase |
[:upper:] | Uppercase |
[:space:] | Whitespace |
[:punct:] | Punctuation |
[:print:] | Printable |
[:cntrl:] | Control characters |
patch vs tr
| Aspect | patch | tr |
|---|---|---|
| Input | Diff file + original | stdin |
| Output | Patched file | stdout |
| Purpose | Apply changes | Translate/delete chars |
| Works on | Lines/hunks | Single characters |
| Companion | diff | sed, awk |
Best Practices
✅ Do This:
# Always use -u with diff when creating patches
diff -u old.txt new.txt > fix.patch # ✅
# Back up before patching
patch -b file.txt < fix.patch # ✅
# Dry run first on important patches
patch --dry-run file.txt < fix.patch # ✅
# Use -p1 for git-generated patches
patch -p1 < fix.patch # ✅
# Use -R to undo a patch
patch -R file.txt < fix.patch # ✅
# Use tr classes for portability
tr '[:upper:]' '[:lower:]' # ✅
# Use tr -cd to keep only what you want
tr -cd '[:digit:]' # ✅
# Use tr -s to squeeze whitespace
tr -s '[:space:]' # ✅
# Remove CR from Windows files
tr -d '\r' < win.txt > unix.txt # ✅
❌ Don’t Do This:
# Don't apply a patch without checking it
patch file.txt < unknown.patch # ❌ may break things
# Don't forget -p when paths are prefixed
patch < fix.patch # ❌ may fail
# Don't patch without a backup on critical files
patch file.txt < fix.patch # ❌ no undo
# Don't use tr for word replacement
tr 'lo' 'LO' # ❌ character-level only
# Don't expect tr to handle regex
tr 'l+' 'L' # ❌ + is literal
# Don't use tr on binary files
tr 'a' 'b' < binary # ❌ corrupts data
# Don't forget quotes around sets
tr a-z A-Z # ⚠️ may shell-expand
# Don't use tr to replace multi-char strings
tr 'hello' 'world' # ❌ maps h→w, e→o, l→r...
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
| Patch fails | Wrong -p level | Try -p0, -p1, -p2 |
.rej files | Hunks rejected | Apply manually |
| No backup | Can’t undo | Use -b |
| Patch already applied | Reversed detection | Use -R or -f |
tr word confusion | Only chars replaced | Use sed |
tr unquoted | Shell expands ranges | Quote: 'a-z' |
tr no stdin | Nothing to translate | Pipe input |
tr with binary | Corrupts data | Use other tools |
tr -d over-deletes | Removes wanted chars | Test with echo first |
tr case classes | Locale-dependent | Set LC_ALL=C if needed |
Real-World Examples
1. Apply a Bug Fix
$ cd project/
$ patch -p1 < /path/to/fix.patch
patching file src/main.c
patching file src/utils.c
2. Create and Apply a Config Patch
$ diff -u config.old config.new > config.patch
$ patch -b config.old < config.patch
patching file config.old
3. Undo a Patch
$ patch -R file.txt < fix.patch
patching file file.txt
4. Dry-Run an Important Patch
$ patch --dry-run -p1 < big-change.patch
checking file src/main.c
checking file src/utils.c
5. Fix Windows Line Endings
$ tr -d '\r' < windows.txt > unix.txt
$ file unix.txt
unix.txt: ASCII text
6. Convert a File to Uppercase
$ tr 'a-z' 'A-Z' < input.txt > output.txt
7. Remove Punctuation from Text
$ echo "Hello, world! How are you?" | tr -d '[:punct:]'
Hello world How are you
8. Keep Only Digits
$ echo "Call 555-1234 or 555-5678" | tr -cd '[:digit:]\n'
555123455556 78
9. Collapse Whitespace
$ echo "too many spaces" | tr -s ' '
too many spaces
10. One Word Per Line
$ echo "the quick brown fox" | tr ' ' '\n'
the
quick
brown
fox
11. ROT13 Cipher
$ echo "hello world" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
uryyb jbeyq
12. Remove Non-Printable Characters
$ tr -cd '[:print:]\n' < messy.txt > clean.txt
13. Tabs to Spaces
$ tr '\t' ' ' < input.txt > output.txt
14. Word Frequency Count
$ cat book.txt | tr -s '[:space:]' '\n' | sort | uniq -c | sort -rn | head -10
5432 the
3210 and
2987 of
15. Normalize Emails to Lowercase
$ cat emails.txt | tr 'A-Z' 'a-z' | sort -u
alice@example.com
bob@example.com
16. Patch a Whole Directory Tree
$ patch -p1 -d /opt/app < update.patch
patching file src/main.c
patching file src/utils.c
17. Check What a Patch Would Do
$ patch --dry-run -p1 < update.patch
18. Reverse a Set of Patches
$ for p in *.patch; do
patch -R -p1 < "$p"
done
Visual: The patch Workflow
┌──────────────────────────────────────────────┐
│ The patch workflow │
│ │
│ file_v1 ─┐ │
│ ├──► diff -u ──► fix.patch │
│ file_v2 ─┘ │
│ │
│ fix.patch contains: │
│ --- file_v1 │
│ +++ file_v2 │
│ @@ -1 +1 @@ │
│ -old line │
│ +new line │
│ │
│ Then: │
│ │
│ file_v1 ──► patch < fix.patch ──► file_v2 │
│ │
│ Small file, big effect │
│ │
└──────────────────────────────────────────────┘
Visual: How tr Works
┌──────────────────────────────────────────────┐
│ tr 'lo' 'LO' │
│ │
│ Input: h e l l o w o r l d │
│ │ │ │ │ │ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ │
│ Map: - - l→L l→L o→O - o→O - l→L - │
│ │ │ │ │ │ │ │ │ │ │ │
│ Output: h e L L O w O r L d │
│ │
│ Character-by-character mapping │
│ │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ tr -d 'lo' │
│ │
│ Input: h e l l o w o r l d │
│ │ │ │ │ │ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ │
│ Delete: - - X X - - X - X - │
│ │ │ │ │ │ │ │
│ Output: h e w r │
│ → "he wrd" │
│ │
│ Deletes every matching character │
│ │
└──────────────────────────────────────────────┘
Summary
| Command | Purpose | Example |
|---|---|---|
diff -u old new > fix.patch | Create a patch | diff -u a b > p.diff |
patch FILE < fix.patch | Apply a patch | patch config.ini < p.diff |
patch -b FILE < fix.patch | With backup | patch -b a.txt < p.diff |
patch -R FILE < fix.patch | Reverse a patch | patch -R a.txt < p.diff |
patch -p1 < fix.patch | Strip path components | patch -p1 < p.diff |
patch --dry-run < fix.patch | Preview | patch --dry-run < p.diff |
patch -i FILE patch | Read patch from file | patch -i p.diff a.txt |
tr 'e' 'E' | Replace a character | echo hello | tr e E |
tr 'lo' 'LO' | Map multiple chars | echo hello | tr lo LO |
tr 'A-Z' 'a-z' | Change case | echo HELLO | tr A-Z a-z |
tr -d 'lo' | Delete characters | echo hello | tr -d lo |
tr -s ' ' | Squeeze repeats | echo "a b" | tr -s ' ' |
tr -c '[:digit:]' ' ' | Complement | tr -c 0-9 ' ' |
tr -cd '[:digit:]' | Keep only digits | tr -cd 0-9 |
tr '\n' ' ' | Newline to space | tr '\n' ' ' |
tr ' ' '\n' | Space to newline | tr ' ' '\n' |
tr -d '\r' | Remove CR | tr -d '\r' |
tr '[:upper:]' '[:lower:]' | Case classes | tr '[:upper:]' '[:lower:]' |
Key takeaways:
patchapplies a diff file to an original — the classic way software updates are distributed- The workflow is:
diff -u old new > fix.patchthenpatch old < fix.patch - Use
-bto back up,-Rto reverse,-p1to strip path components - Use
--dry-runbefore applying important patches - Failed hunks go to
.rejfiles — apply them manually trtranslates or deletes single characters from stdin → stdout- Use
-dto delete,-sto squeeze,-cfor complement - Use
[:upper:]/[:lower:]for case conversion trcannot replace words — it’s character-level only; usesedfor that- Use
tr -d '\r'to fix Windows line endings - Use
tr ' ' '\n'to turn a sentence into one word per line - Both tools are pipelines — combine them with
sort,uniq,grep, andsed
Remember: patch is how changes travel — small diff files that transform one version into another. Always use diff -u to create patches, always back up before applying, and always dry-run on critical files. tr is the simplest character filter — translate, delete, squeeze. It doesn’t understand words or patterns, only individual characters. When you need word replacement, reach for sed; when you need to map every a to b, tr is the fastest tool for the job.
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!