The tr Command Explained: Translating and Deleting Characters

The tr Command Explained: Translating and Deleting Characters

tr is the smallest member of the text-processing family: it translates characters, deletes characters, or squeezes repeats, and that is the entire feature list. Its value comes from how often exactly one of those three operations is the missing step in a pipeline.

The mental model

tr SET1 SET2 maps each character in SET1 to the character at the same position in SET2, applied to every character flowing through:

echo "hello world" | tr 'a-z' 'A-Z'
# HELLO WORLD

echo "hello" | tr 'el' 'ip'
# hippo

Two things to internalize immediately: tr works on characters, never strings or patterns (that is sed’s job), and tr reads only standard input; tr 'a-z' 'A-Z' file.txt is an error. Redirect or pipe input in.

Case conversion

tr '[:lower:]' '[:upper:]' < notes.txt
tr '[:upper:]' '[:lower:]' < SHOUTING.TXT

The bracketed character classes ([:lower:], [:upper:], [:digit:], [:alnum:], [:space:]) are locale-aware and safer than literal ranges when input may contain accented characters.

Deleting characters with -d

-d drops every occurrence of the listed characters:

# Strip Windows carriage returns
tr -d '\r' < windows.txt > unix.txt

# Remove all digits
echo "user123name456" | tr -d '[:digit:]'
# username

# Remove everything EXCEPT digits (complement with -c)
echo "call 555-0142 now" | tr -cd '[:digit:]'
# 5550142

The \r deletion is the one you will use forever: files edited on Windows carry carriage returns that make scripts fail with cryptic errors like bad interpreter: /bin/bash^M. One tr pass fixes the file.

Squeezing repeats with -s

-s collapses runs of a repeated character to a single occurrence, which is the standard preparation step before cut on space-aligned output:

# Aligned columns -> single-space separated -> cuttable
df -h | tr -s ' ' | cut -d' ' -f1,5

# Collapse blank-line runs is better served by cat -s, but squeezing newlines works on repeated \n
tr -s '\n' < file.txt

Combined translate-and-squeeze also works: tr -s ' \t' ' ' converts any run of spaces and tabs into a single space.

Translating delimiters

Converting one separator to another is pure tr territory:

# Colon-separated PATH, one entry per line
echo "$PATH" | tr ':' '\n'

# Newline-separated list to comma-separated
tr '\n' ',' < items.txt

# Spaces to underscores for a filename
echo "my file name" | tr ' ' '_'

The PATH one-liner is genuinely useful for eyeballing what your shell will search and in what order.

A word-frequency pipeline

The classic demonstration composes tr with sort and uniq into a word counter:

tr -cs '[:alpha:]' '\n' < article.txt \
  | tr '[:upper:]' '[:lower:]' \
  | sort | uniq -c | sort -rn | head

The first tr replaces every run of non-letters with a newline, isolating one word per line; the second lowercases; the rest counts and ranks. Four small tools, a working word-frequency analysis.

What tr cannot do

tr has no concept of context, position, words, or patterns. It cannot replace “cat” with “dog” (both share the letter loop through positional mapping, mangling other text), cannot operate on only part of a line, and cannot make replacements conditional. The moment a transformation involves anything beyond individual characters applied uniformly, move up to sed or awk. Knowing that boundary is most of knowing tr.

Frequently Asked Questions

What does the tr command do?

tr reads standard input and translates, squeezes, or deletes characters, writing the result to standard output. It works character by character, not on words or patterns.

Why does tr file.txt not work?

tr takes no filename arguments and only reads standard input. Redirect the file in with tr … < file.txt or pipe into it. This differs from most text tools and is the most common tr mistake.

How do I convert text to uppercase with tr?

Pipe through tr ‘a-z’ ‘A-Z’, or the locale-safe form tr ’[:lower:]’ ’[:upper:]’. Every character in the first set is replaced by the character at the same position in the second set.

How do I remove Windows carriage returns from a file?

Use tr -d ‘\r’ < windows.txt > unix.txt. The -d flag deletes every occurrence of the listed characters. The dos2unix tool does the same job with a friendlier interface.

What does tr -s do?

The -s flag squeezes runs of repeated characters down to one occurrence. tr -s applied to spaces is the classic preparation step before cutting columns from aligned output.

Can tr replace words or strings?

No. tr operates strictly on single characters, mapping set one to set two positionally. To replace words or multi-character strings, use sed instead.