Viewing files
cat
Concatenate files and print them to standard output; also the quickest way to see a short file.
cat [OPTION...] [FILE...]
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
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
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
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
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
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
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
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
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
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
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
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
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
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 > adestroysa: the shell empties the output file beforecatruns. Write to a temporary file andmvit over the original.A file with CRLF line endings looks normal with plain
cat. Usecat -A(orcat -v) when a script fails with$'\r': command not foundor similar.Don't
cata binary file to the terminal: escape sequences inside it can scramble the terminal's state. Usexxd,odorfileto inspect it, andresetif it already happened.cat *.logjoins 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,-Eand-Tand all long options (--number,--show-all) are GNU. BSD/macOScathas-e(line ends as$, implies-v),-t(tabs as^I, implies-v),-v,-n,-band-s; usecat -etthere for roughly whatcat -Adoes.
Options worth knowing
A selection, described in our own words. For the full list, see cat(1) or cat --help.
| Option | What it does |
|---|---|
-n, --number | Number every output line. |
-b, --number-nonblank | Number only non-empty lines; overrides -n. |
-s, --squeeze-blank | Collapse repeated empty lines into one. |
-A, --show-all | Show tabs, line ends and other non-printing characters; same as -vET. |
-E, --show-ends | Print $ at the end of each line. |
-T, --show-tabs | Print tab characters as ^I. |
-v, --show-nonprinting | Show control and high-bit characters in ^ and M- notation, except tab and newline. |
-e | Same as -vE. |
-t | Same as -vT. |
-u | Ignored; accepted for POSIX compatibility. |
Related
tacPrint files with their lines in reverse order, last line first.lessPage through a file or command output one screen at a time, with search and scrolling in both directions.headPrint the first lines (or bytes) of files; 10 lines by default.tailPrint the last lines of files, or follow a file as it grows with -f.nlPrint files with line numbers added, with control over which lines get numbered and how.teeCopy standard input to standard output and to one or more files at the same time.xxdMake a hex dump of a file, or turn a hex dump back into binary with -r.- Here-documents and here-stringsFeed multi-line text to a command with <<EOF, stop expansion with a quoted delimiter, indent with <<-, and pass one string with <<<.
- RedirectionHow >, >>, 2>, 2>&1, &>, < and exec move a command's input and output between files and file descriptors, and why the order matters.