tr Command in Linux: Translate, Delete, and Squeeze Text

When text needs character-level cleanup, this tr command guide shows how to convert case, delete unwanted bytes, squeeze repeated spaces, repair CRLF endings, and avoid unsafe file redirects.

PublishedAuthorJoshua JamesRead time9 minGuide typeLinux Commands

Text streams often need one-character cleanup before heavier tools make sense. The tr command in Linux translates, deletes, and squeezes characters from standard input, which makes it useful for case conversion, delimiter cleanup, CRLF repair, log normalization, and simple pipeline preparation.

Use tr when the job is character-based. Line matching, word replacement, and field-aware reports belong to other text tools, so keep tr focused on the cleanup layer it actually owns.

Understand the tr Command in Linux

The tr command reads from standard input and writes to standard output. It does not open files by filename the way sed, awk, or grep can. Pipe text into it, redirect a file into it, or type input interactively and end the stream with Ctrl+D.

tr [OPTION]... SET1 [SET2]

A minimal pipeline is enough for a first check: pipe text into tr, choose one character to replace, and read the transformed output from stdout.

printf 'alpha,beta,gamma\n' | tr ',' '\n'
alpha
beta
gamma

The GNU tr manual is the best reference when your system uses GNU coreutils. Its four core operations match the practical model for most Linux systems: translate characters, squeeze repeated characters, delete characters, and delete characters before squeezing repeats. The GNU character-array documentation explains ranges, character classes, escapes, and locale-sensitive input.

How tr Reads SET1 and SET2

SET1 names the input characters that tr should act on. SET2 names the replacement characters when translation is active. These sets are character arrays, not regular expressions, so patterns such as ., *, and ^ do not mean the same thing they mean in regex tools.

  • Translate: tr 'abc' 'xyz' maps a to x, b to y, and c to z.
  • Delete: tr -d '[:digit:]' removes digits and prints the remaining characters.
  • Squeeze: tr -s '[:blank:]' replaces repeated horizontal whitespace with one copy of the same character.
  • Complement: tr -cd '[:alnum:]\n' keeps letters, digits, and newlines while deleting everything else.

Common tr Command Patterns

Use these patterns when the input is character-based and already comes from standard input, a pipe, or file redirection.

TaskCommand PatternWhen to Use It
Uppercase texttr '[:lower:]' '[:upper:]'Convert ASCII letters while leaving digits and punctuation alone.
Delete digitstr -d '[:digit:]'Remove numeric characters from a stream.
Keep safe characterstr -cd '[:alnum:]\n'Keep letters, digits, and line breaks while dropping punctuation and spaces.
Normalize horizontal spacingtr -s '[:blank:]' ' 'Collapse spaces and tabs without joining separate lines.
Split simple liststr ',' '\n'Turn comma-separated values into one value per line when quoting is not involved.
Repair CRLF endingstr -d '\r'Remove carriage returns from Windows-style text files.

Common tr Character Sets

Character classes are usually clearer than hand-written ranges, especially when scripts may run under different locales. Quote them so the shell does not treat brackets as filename patterns.

SetMeaningCommon Use
[:lower:]Lowercase letters.Translate to [:upper:] for uppercase output.
[:upper:]Uppercase letters.Translate to [:lower:] for lowercase output.
[:digit:]Decimal digits.Delete numbers or keep only numeric characters.
[:alnum:]Letters and digits.Build word lists or keep identifier-like text.
[:blank:]Spaces and tabs.Normalize horizontal spacing without deleting newlines.
[:space:]Whitespace, including newlines.Collapse all whitespace when line boundaries do not matter.
[:punct:]Punctuation characters.Remove punctuation from simple text streams.
\n, \r, \tNewline, carriage return, and tab escapes.Repair line endings or convert delimited text.

Use tr for ASCII-safe cleanup, delimiters, whitespace, and byte-oriented transformations. GNU documentation warns that multibyte locales are not portable for arbitrary character translation, so use a Unicode-aware language when you need multilingual case folding or normalization.

Verify tr Availability and Build Example Files

Linux systems normally provide tr through a coreutils package. Many systems use GNU coreutils, some newer systems may use compatible implementations such as uutils coreutils, and minimal containers or rescue shells may expose a smaller BusyBox applet. Check the command path and implementation before relying on exact error text or implementation-specific behavior.

command -v tr

The command returns the executable path your shell will use. The directory can differ by distribution or system layout; this is common example output:

/usr/bin/tr

Most full coreutils implementations provide a version banner. BusyBox and other compact implementations may use different help or version output.

tr --version | head -1

GNU output begins with the implementation and coreutils release:

tr (GNU coreutils) 9.11

Systems that ship uutils coreutils can show a banner like this instead:

tr (uutils coreutils) 0.8.0

If tr --version is unsupported, use tr --help to confirm the available options before copying GNU-specific examples into a minimal container, rescue shell, or alternate coreutils implementation.

Create a disposable workspace for the file-based examples. The sample files cover CSV-like rows, uneven log spacing, CRLF line endings, punctuation, and simple identifiers.

mkdir -p ~/tr-demo
cd ~/tr-demo

printf '%s\n' \
  'Web-01,Frontend,ACTIVE' \
  'API-02,Backend,Maintenance' \
  'DB-03,Database,ACTIVE' > services.csv

printf '%s\n' \
  '2026-06-15 10:00:01 INFO request completed' \
  '2026-06-15 10:00:02 WARN  retry pending' \
  '2026-06-15 10:00:03 ERROR  upstream timeout' > events.log

printf 'name\trole\tstatus\r\nweb-01\tfrontend\tactive\r\napi-02\tbackend\tmaintenance\r\n' > windows.tsv

printf '%s\n' \
  'Alpha!!!   Beta?? Gamma---Delta' \
  'ticket=LC-1042; owner=ops_team; status=OPEN' > messy.txt

ls -1

The workspace should contain four files:

events.log
messy.txt
services.csv
windows.tsv

The examples use printf command examples to generate predictable input. That keeps the output stable and avoids depending on files already present on your system.

Translate Characters with tr

Translation uses both SET1 and SET2. Each character from SET1 maps to the character in the same position in SET2. Characters outside SET1 pass through unchanged.

Convert Lowercase Text to Uppercase

Use the paired [:lower:] and [:upper:] classes for case conversion instead of ASCII ranges when the input is ordinary English text.

printf '%s\n' 'Linux 2026' | tr '[:lower:]' '[:upper:]'
LINUX 2026

Lowercase a File Without Editing It

Redirect a file into tr when you want to transform file content. The command reads from services.csv and prints the lowercase result to the terminal.

tr '[:upper:]' '[:lower:]' < services.csv
web-01,frontend,active
api-02,backend,maintenance
db-03,database,active

Replace Spaces and Hyphens with Underscores

When several input characters should become the same output character, give SET2 the same length as SET1. Here, both space and hyphen map to underscores.

printf '%s\n' 'web-01 frontend active' | tr ' -' '__'
web_01_frontend_active

Some implementations pad a short SET2 by repeating its final character, but scripts are easier to read and more portable when the mapping is explicit.

Split a Delimited List into Lines

Translate commas into newlines when a short list needs one value per line. This is character translation, not CSV parsing, so keep it for simple unquoted lists.

printf 'alpha,beta,gamma\n' | tr ',' '\n'
alpha
beta
gamma

Split a PATH-Style List into Lines

Colon-separated lists such as PATH-style values are easier to inspect when each path appears on its own line. Use a fixed sample string when you are teaching or testing the pattern so the output does not depend on your current shell environment.

printf '/usr/local/bin:/usr/bin:/bin\n' | tr ':' '\n'
/usr/local/bin
/usr/bin
/bin

Convert Tabs to Commas After Removing CRLF Characters

The sample windows.tsv file contains tab separators and Windows-style carriage returns. Delete \r first, then translate each tab into a comma.

tr -d '\r' < windows.tsv | tr '\t' ','
name,role,status
web-01,frontend,active
api-02,backend,maintenance

Delete Characters with tr

The -d option removes characters in SET1. Do not provide SET2 for a plain delete operation.

Remove Punctuation and Horizontal Space

Combine character classes when the same delete rule should cover several groups. [:blank:] removes spaces and tabs without deleting the final newline.

printf 'Phone: +1 (555) 0199\n' | tr -d '[:punct:][:blank:]'
Phone15550199

Keep Only Letters, Digits, and Newlines

Use -c with -d to delete the complement of SET1. Include \n when the output should preserve line breaks.

printf 'Order #LC-1042: ready.\n' | tr -cd '[:alnum:]\n'
OrderLC1042ready

Extract Digits from Mixed Text

Complement delete mode is useful when you only need the numeric characters from an identifier, invoice, or pasted value. Keep the newline so the shell prompt does not run into the result.

printf 'Invoice LC-2026-0042\n' | tr -cd '[:digit:]\n'
20260042

This pattern concatenates digit groups. Use a field-aware tool when separators or number boundaries matter.

Remove Carriage Returns from Windows Text

Windows text files often end lines with carriage return plus newline. Deleting \r leaves normal Unix-style newline characters in place.

printf 'first\r\nsecond\r\n' | tr -d '\r' | cat -v
first
second

The cat -v check makes control characters visible when they remain. If you use cat for other file-inspection workflows, the cat command in Linux guide covers safe viewing and concatenation patterns.

Remove NUL Bytes from a Stream

NUL bytes can appear in copied logs, exported text, or streams that accidentally include binary data. Delete them only when the input is supposed to be plain text; do not use this pattern on files that need their binary structure preserved.

printf 'alpha\0beta\n' | tr -d '\000' | cat -v
alphabeta

Squeeze Repeated Characters with tr

The -s option collapses adjacent repeated characters from the active set. Squeezing is useful after translation because several different input characters can become the same output character.

Normalize Spaces and Tabs

Translate spaces and tabs to one regular space, then squeeze repeated spaces. This keeps the line structure intact while making columns easier to scan or pipe into another tool.

printf 'alpha     beta\t\tgamma\n' | tr -s '[:blank:]' ' '
alpha beta gamma

The same pattern cleans the uneven spacing in the sample log:

tr -s '[:blank:]' ' ' < events.log
2026-06-15 10:00:01 INFO request completed
2026-06-15 10:00:02 WARN retry pending
2026-06-15 10:00:03 ERROR upstream timeout

Convert Repeated Delimiters to One Item per Line

Translate-and-squeeze mode can clean simple delimiter runs in one step. This maps one or more commas to a single newline, which is useful for quick lists but not for CSV data where empty fields have meaning.

printf 'alpha,,beta,,,gamma\n' | tr -s ',' '\n'
alpha
beta
gamma

Remove Repeated Blank Lines

Squeeze repeated newline characters when a stream has accidental blank-line runs.

printf 'one\n\n\nthree\n' | tr -s '\n'
one
three

Combine tr in Text Pipelines

The strongest tr workflows usually prepare text for another command. Keep tr responsible for character cleanup, then hand line matching, substitutions, field logic, sorting, or aggregation to the tool that owns that layer.

Normalize Log Case Before Matching Lines

Case and spacing can vary in pasted logs and small exports. Normalize the stream with tr, then use the grep command in Linux for the line match.

tr '[:upper:]' '[:lower:]' < events.log | tr -s '[:blank:]' ' ' | grep 'error'
2026-06-15 10:00:03 error upstream timeout

Build One Word per Line

The -c and -s options can turn non-alphanumeric runs into a single newline. The [\n*] form tells tr to repeat newline as many times as needed for the translated set, which avoids relying on GNU’s short-SET2 padding behavior.

printf 'Alpha!!! Beta?? Gamma---Delta\n' | tr -cs '[:alnum:]' '[\n*]'
Alpha
Beta
Gamma
Delta

Apply the same cleanup to the sample file:

tr -cs '[:alnum:]' '[\n*]' < messy.txt
Alpha
Beta
Gamma
Delta
ticket
LC
1042
owner
ops
team
status
OPEN

Build an ASCII Slug from a Title

For simple ASCII titles, combine translation, complement delete mode, and squeezing to create a lowercase token. Set LC_ALL=C for byte-ordered ranges, and use a Unicode-aware tool when titles contain non-ASCII letters that must be preserved or normalized.

printf '%s\n' 'Quarterly Report: June 2026!' | LC_ALL=C tr '[:upper:] ' '[:lower:]-' | tr -cd '[:alnum:]-\n' | tr -s '-'
quarterly-report-june-2026

Show Where tr Stops Being the Right Tool

tr transforms individual characters, not words. A command that looks like it should change cat to dog actually maps c to d, a to o, and t to g wherever those characters appear.

printf 'cat catalog\n' | tr 'cat' 'dog'
dog dogolog

Use sed for find-and-replace text workflows, then use tr before or after it when the input still needs character-level cleanup. Use awk command examples when the next step depends on fields, columns, or calculations rather than individual characters.

Use tr Safely in Files and Scripts

tr writes to standard output by design. That is safer for previews, but it means file edits need a temporary output file and a deliberate replacement step.

Preview File Changes Before Replacing a File

Write transformed output to a new file, inspect it, then replace the original only when the result is correct. This pattern prevents accidental truncation from redirecting back to the same input file.

tr '[:upper:]' '[:lower:]' < services.csv > services.lower.csv
head -3 services.lower.csv
web-01,frontend,active
api-02,backend,maintenance
db-03,database,active

If the preview is correct, replace the original file with the transformed copy. The mv command guide covers broader move, rename, and overwrite patterns when the replacement step becomes more complex.

mv services.lower.csv services.csv
head -3 services.csv
web-01,frontend,active
api-02,backend,maintenance
db-03,database,active

Do not use tr ... < file > file. The shell opens the output file for writing before tr reads the input, which can empty the file before the command processes it.

Use the C Locale for Byte-Oriented Ranges

Character classes are usually preferable, but some scripts intentionally operate on byte ranges. Set LC_ALL=C for that command so ranges such as A-Z and 0-9 use the byte order the script expects.

printf 'ABC-123\n' | LC_ALL=C tr 'A-Z' 'a-z'
abc-123

For ordinary case conversion, tr '[:upper:]' '[:lower:]' is clearer than ranges and avoids most locale surprises.

Troubleshoot Common tr Errors

Most tr failures come from treating filenames as operands, omitting the second set during translation, deleting the newline by accident, or putting a hyphen where option parsing can consume it.

tr Reports Extra Operand for a Filename

The error appears when a filename is placed after the two character sets. tr expects input through standard input, so it treats the filename as a third operand.

LC_ALL=C tr '[:lower:]' '[:upper:]' services.csv
tr: extra operand 'services.csv'
Try 'tr --help' for more information.

Redirect the file into tr instead:

tr '[:lower:]' '[:upper:]' < services.csv | head -2
WEB-01,FRONTEND,ACTIVE
API-02,BACKEND,MAINTENANCE

tr Reports Missing Operand During Translation

Translation needs both SET1 and SET2. If only one set is provided without a mode such as -d or -s, tr fails before reading useful input.

printf 'abc\n' | LC_ALL=C tr '[:lower:]'
tr: missing operand after '[:lower:]'
Two strings must be given when translating.
Try 'tr --help' for more information.

Choose a real translation target, or switch to delete mode when the task is removal:

printf 'abc123\n' | tr -d '[:digit:]'
abc

tr Treats a Hyphen as an Option or Range

A leading hyphen can be parsed as an option, and a hyphen between characters can define a range. This can affect delete, squeeze, and translate sets when the set starts with -. Implementations differ in exact wording, but the failure usually appears as an invalid option or unexpected argument.

printf 'a-b\n' | LC_ALL=C tr -d -ab
tr: invalid option -- 'a'
Try 'tr --help' for more information.

GNU tr prints wording like the output above. Compatible implementations may describe the same mistake differently; for example, uutils tr reports an unexpected -a argument and suggests -- -a.

Terminate option parsing before the set when a character set begins with a hyphen:

printf 'a-b-c\n' | tr -d -- '-ab'
c

tr Removes the Final Newline

Complement deletes remove every character outside the keep set. If the keep set omits \n, the output may print without a final line break and look merged with the next command output. The NEXT marker makes that missing line break visible.

printf 'abc123\n' | tr -cd '[:alpha:]'; printf 'NEXT\n'
abcNEXT

The visible letters are correct, but the newline was deleted with the digits. Keep newline when line structure matters:

printf 'abc123\n' | tr -cd '[:alpha:]\n'; printf 'NEXT\n'
abc
NEXT

tr Waits for Input and Looks Stuck

A bare tr command waits because it is reading standard input from the terminal. Type text and press Ctrl+D to end interactive input, or provide input with a pipe or redirection.

printf 'ready\n' | tr '[:lower:]' '[:upper:]'
READY

Clean Up the tr Demo Files

Remove the disposable workspace after finishing the examples. This command targets only the demo directory created earlier; review rm command examples before adapting recursive deletion to other paths.

cd ~
rm -rf -- ~/tr-demo

Conclusion

tr is ready for character-level cleanup in Linux pipelines: translate case, delete unwanted bytes, squeeze repeated whitespace, repair CRLF endings, and prepare simple word streams before handing richer parsing to grep, sed, or awk. Keep previews on stdout, redirect files deliberately, and use character classes when scripts need to survive across shells and locales.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<a href="https://example.com">link</a> link
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Verify before posting: