tr
Translate, squeeze, or delete characters from input
By CMD Script Team · 4 min read · Last updated
tr [OPTIONS] SET1 [SET2]Options
| Flag | Description |
|---|---|
-d | Delete characters in SET1 from the input, no SET2 needed |
-s | Squeeze consecutive repeated characters in SET1 down to a single instance |
-c | Complement SET1: operate on all characters NOT in the set |
-t | Truncate SET1 to the length of SET2 before mapping (GNU tr default behavior) |
a-z A-Z | Common character ranges used as SET1/SET2 for case conversion |
Distribution compatibility
- Ubuntu
- Debian
- Fedora
- Arch
- macOS (BSD tr, character class syntax like [:upper:] is supported the same way)
What it does
tr (translate) reads characters from standard input and, character by character,
translates, squeezes, or deletes them according to two character sets you provide. It has
no concept of files, lines, or fields — it works purely on the character stream, which
makes it fast for simple, uniform transformations like case conversion, stripping
unwanted characters, or collapsing repeated characters, but unsuitable for anything
pattern- or context-based (that's sed's job).
Beginner examples
echo "Hello" | tr 'a-z' 'A-Z'— uppercase all lowercase letterstr -d '0-9' < file.txt— delete every digit from the inputtr -s ' ' < file.txt— squeeze multiple spaces into onetr '\n' ' ' < file.txt— replace every newline with a space
echo "CMD Script" | tr 'a-z' 'A-Z'
Advanced examples
- Strip carriage returns to convert Windows line endings to Unix:
tr -d '\r' < windows.txt > unix.txt - Keep only alphanumeric characters, deleting everything else with
-c(complement):tr -cd '[:alnum:]\n' < messy.txt - Flatten a newline-separated list into a comma-separated one:
tr '\n' ',' < list.txt | sed 's/,$/\n/' - Count word frequency by splitting on whitespace into one word per line first:
tr -s ' ' '\n' < file.txt | sort | uniq -c | sort -rn - Rot13-encode text using two mapped 26-character ranges:
tr 'A-Za-z' 'N-ZA-Mn-za-m' < message.txt
tr -s ' \t' '\n' < document.txt | sort | uniq -c | sort -rn | head
Common mistakes
- Trying to pass a filename directly to
tr(tr 'a-z' 'A-Z' file.txt) — it doesn't accept file arguments; you must redirect input with<or pipe it in. - Forgetting
-ddoesn't need a SET2 —tr -d '0-9' 'x'is a mistake; deletion only takes one character set. - Assuming
trunderstands regular expressions — it only works on literal character sets and ranges (a-z,[:digit:]), not patterns likesedorgrepuse. - Using unequal-length SET1/SET2 for translation without realizing GNU
trtruncates SET2 or extends it by repeating its last character, which can produce unexpected mappings.
Tips
- Use POSIX character classes like
[:upper:],[:lower:],[:digit:],[:punct:]instead of raw ranges (A-Z) for correctness across locales. - Combine
-sand-din sequence via a pipeline for multi-step character cleanup, since a singletrinvocation only applies one transformation. tr -c(complement) is useful for keeping only a known-good character set and deleting everything else, e.g. sanitizing input to alphanumerics.
Best practices
- Reach for
tronly for simple, whole-stream character-level transformations; once you need context, patterns, or per-line logic, switch tosedorawk. - Always redirect or pipe input into
tr— never expect it to accept a filename argument like most other text tools. - Prefer POSIX character classes (
[:alpha:],[:space:]) over hardcoded ranges when scripts need to work correctly under different locales.
Try it yourself
A simulated shell with a sample home directory — experiment freely, nothing leaves your browser. Type help to list supported commands.
Real-world use cases
- Normalizing text case before a case-insensitive comparison in a shell script:
[ "$(echo "$input" | tr 'A-Z' 'a-z')" = "yes" ]. - Cleaning up files transferred from Windows systems by stripping carriage returns:
tr -d '\r' < report.csv > report_unix.csv. - Quick word-frequency analysis of a text file by splitting on whitespace and counting:
tr -s ' ' '\n' < essay.txt | sort | uniq -c | sort -rn.
Common interview questions
- Why can't you run
tr 'a-z' 'A-Z' file.txtdirectly on a file?tronly reads from standard input; it has no file-argument support, so input must be redirected (< file.txt) or piped in. - What's the difference between
tr -dandtr -s?-ddeletes every occurrence of characters in SET1 from the input;-ssqueezes consecutive repeats of characters in SET1 down to a single instance, without deleting isolated occurrences. - How would you strip Windows-style line endings from a file using
tr?tr -d '\r' < file.txt > file_unix.txtremoves the carriage return character, leaving Unix-style line feeds.
Frequently Asked Questions
How do I uppercase or lowercase text with tr?
Use tr 'a-z' 'A-Z' to uppercase, or tr 'A-Z' 'a-z' to lowercase. For portability across locales, prefer tr '[:lower:]' '[:upper:]' with POSIX character classes.
Why does tr only take stdin and not a filename argument?
tr is designed purely as a stream filter — it reads standard input and writes standard output, with no concept of file arguments. Redirect a file in with < file or pipe it: cat file | tr ... or tr ... < file.
How do I delete specific characters from text?
Use -d with the set of characters to remove, e.g. tr -d '0-9' removes all digits, or tr -d '\r' strips carriage returns from Windows-formatted text files.
What does tr -s do?
It squeezes (collapses) consecutive repeats of characters in SET1 into a single occurrence — useful for collapsing multiple spaces into one: tr -s ' ' ' ' < file, or more simply tr -s ' '.
Cheat sheet
Download a quick-reference cheat sheet for tr.