opscape

Viewing files

cat

Concatenate files and print them to standard output; also the quickest way to see a short file.

cat [OPTION...] [FILE...]

13 of 13 examples run in Debian 13.7 on 2026-10-31 · coreutils 9.7-3 · manual: cat(1)

cat reads each file you name, in order, and writes the bytes to standard output unchanged. With no file, or with - as a file name, it reads standard input. That is the whole tool: the name comes from concatenate, and joining files end to end is still its real job.

For looking at a file, cat is right when the file is short enough to fit on screen. For anything longer use less (scrollable, searchable) or head / tail. The handful of options worth knowing make invisible characters visible: -A shows tabs, carriage returns and line ends, which is the fastest way to diagnose a file that "looks fine" but breaks a script.

cat file | grep x works, but grep x file does the same with one process less. Reach for cat in a pipeline when you need to join several inputs into one stream.

Examples

Print a short file

cat todo.txt
explain
output
buy milk
fix login bug
write tests
fix logout bug
deploy v2.4

The file's five lines are written to the terminal exactly as stored.

Join several files into one stream

cat logs/app.log.1 logs/error.log
explain
output
2026-03-13 23:58:12 INFO  nightly backup started
2026-03-13 23:59:40 INFO  nightly backup finished: 1.2G in 88s
2026-03-13 23:59:59 INFO  log rotated
[2026-03-14 08:16:40] database timeout after 5000ms (host=db01)
[2026-03-14 08:30:00] disk usage on /var at 91%

The files are printed one after another, in the order given, with nothing between them. The first three lines come from app.log.1, the last two from error.log.

Combine files into a new file

cat logs/app.log.1 logs/app.log > combined.log
wc -l combined.log
output
15 combined.log

Redirecting the output creates combined.log with the 3 older lines followed by the 12 current ones, 15 in total. Order matters: list the older file first to keep the timeline.

Number every line

cat -n notes.txt
explain
output
     1	Meeting notes, March
     2	- Move backups to the new server
     3	- Rotate the API key before Friday
     4	- Check disk usage on web01
     5	- TODO: write the deploy script
     6	Ask Priya about the error rate on web02.

-n puts a right-aligned line number and a tab in front of each line.

Number only the non-empty lines

cat -b data/settings.conf
explain
output
     1	# demo service settings
     2	host = 0.0.0.0
     3	port = 8080

     4	# logging
     5	log_level = info
     6	log_file = /var/log/demo/app.log
     7	# max_connections = 100
     8	timeout = 30

-b skips blank lines when counting, so the empty line after port = 8080 gets no number and the count runs to 8 instead of 9.

Reveal Windows line endings

cat -A data/windows.txt
explain
output
line one^M$
line two^M$

-A marks each line end with $ and shows control characters in caret notation. The ^M before every $ is a carriage return: this file has CRLF (Windows) line endings, which break shell scripts and confuse grep 'one$'.

Tell tabs from spaces

cat -T data/inventory.tsv
explain
output
name^Iqty^Iprice
widget^I12^I4.50
gadget^I3^I19.99
gizmo^I5^I12.00

-T prints each tab as ^I, proving the columns are tab-separated and not padded with spaces.

Collapse runs of blank lines

printf 'first\n\n\n\nsecond\n\n\nthird\n' | cat -s
explain
output
first

second

third

-s keeps at most one empty line in a row. Three or four consecutive blank lines become a single one; the text lines are untouched.

Insert standard input between files

echo '--- current log ---' | cat logs/app.log.1 - logs/error.log
explain
output
2026-03-13 23:58:12 INFO  nightly backup started
2026-03-13 23:59:40 INFO  nightly backup finished: 1.2G in 88s
2026-03-13 23:59:59 INFO  log rotated
--- current log ---
[2026-03-14 08:16:40] database timeout after 5000ms (host=db01)
[2026-03-14 08:30:00] disk usage on /var at 91%

A lone - stands for standard input, so the piped separator line lands exactly where the - appears in the argument list.

Write a small file from the shell

cat > hello.txt <<'EOF'
Hello from a here-document.
$HOME is not expanded because the delimiter is quoted.
EOF
cat hello.txt
output
Hello from a here-document.
$HOME is not expanded because the delimiter is quoted.

cat with no file argument copies its standard input, which here is the here-document. The quoted 'EOF' turns off expansion, so $HOME is written literally.

A missing file does not stop the others

cat todo.txt missing.txt README.md
explain
outputexit 1
buy milk
fix login bug
write tests
fix logout bug
deploy v2.4
cat: missing.txt: No such file or directory
# demo

A small sample project used by every example on this site.
It has logs, CSV and JSON data, a little source code and some photos.

## Layout

- data/  CSV, JSON and text files
- src/   source code
- logs/  application logs

cat reports the missing file on standard error, carries on with README.md, and exits with status 1 at the end because one input failed.

Appending a file to itself is refused

cat notes.txt >> notes.txt
echo "exit status: $?"
wc -l notes.txt
output
cat: notes.txt: input file is output file
exit status: 1
6 notes.txt

GNU cat notices that the input and the output are the same file and refuses instead of looping forever. The file still has its original 6 lines.

The trap: redirecting onto an input file

cat todo.txt notes.txt > todo.txt
cat todo.txt
output
Meeting notes, March
- Move backups to the new server
- Rotate the API key before Friday
- Check disk usage on web01
- TODO: write the deploy script
Ask Priya about the error rate on web02.

The shell truncates todo.txt before cat even starts, so by the time cat reads it the file is empty. The result holds only the notes: the to-do list is gone, and there was no error message. Write to a new file and rename it instead.

Common pitfalls

  • cat a b > a destroys a: the shell empties the output file before cat runs. Write to a temporary file and mv it over the original.

  • A file with CRLF line endings looks normal with plain cat. Use cat -A (or cat -v) when a script fails with $'\r': command not found or similar.

  • Don't cat a binary file to the terminal: escape sequences inside it can scramble the terminal's state. Use xxd, od or file to inspect it, and reset if it already happened.

  • cat *.log joins files in the shell's glob order (alphabetical in the current locale), not by date. Name them explicitly when order matters.

GNU vs BSD and macOS

The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).

  • -A, -E and -T and all long options (--number, --show-all) are GNU. BSD/macOS cat has -e (line ends as $, implies -v), -t (tabs as ^I, implies -v), -v, -n, -b and -s; use cat -et there for roughly what cat -A does.

Options worth knowing

A selection, described in our own words. For the full list, see cat(1) or cat --help.

OptionWhat it does
-n, --numberNumber every output line.
-b, --number-nonblankNumber only non-empty lines; overrides -n.
-s, --squeeze-blankCollapse repeated empty lines into one.
-A, --show-allShow tabs, line ends and other non-printing characters; same as -vET.
-E, --show-endsPrint $ at the end of each line.
-T, --show-tabsPrint tab characters as ^I.
-v, --show-nonprintingShow control and high-bit characters in ^ and M- notation, except tab and newline.
-eSame as -vE.
-tSame as -vT.
-uIgnored; accepted for POSIX compatibility.

Related