cat prints the contents of files to your terminal. It is one of the first commands people learn on Linux, and it also joins files end to end and shows the tabs and Windows line endings that break scripts but don't show up in an editor.
Reading a file
Give cat a file name and it writes the whole file to the terminal, top to bottom, then gives you back the prompt:
cat orders.txtsalmon x2
tuna x3
cod x1cat reads the file and copies every byte to standard output, the stream your terminal displays by default. Because the output is a stream, you can also send it into a file or into another command, and the rest of this page builds on that.
Joining files: what the name means
The name has nothing to do with cats. It is short for 'concatenate', which means joining things end to end. Give cat more than one file and it prints the first, then the next, in the order you listed them:
cat monday.txt tuesday.txtIt adds nothing between them, not even a blank line, so the files run together exactly as they are stored.
cat is older than Linux by about twenty years. It was already in the first edition of the Unix manual in 1971, and the version on most Linux systems today comes from GNU coreutils.
Saving the result
The shell's > sends a command's output to a file instead of the terminal. Put it after cat and the joined files become a new file:
cat monday.txt tuesday.txt > week.txt> creates week.txt if it doesn't exist, and empties it first if it does. To add to the end of a file instead, use >>:
cat wednesday.txt >> week.txtThe redirect is the shell's work, not cat's. The shell opens (and empties) the file before cat starts, and cat never knows its output is going anywhere but the screen.
Because cat copies bytes without looking at them, joining works on any file, not only text. A large download that split cut into backup.tar.part-aa, backup.tar.part-ab and so on goes back together with one command, since the shell sorts the matching names alphabetically:
cat backup.tar.part-* > backup.tarSeeing what's hiding: -n and -A
-n numbers every line of the output, which helps when an error message points you at line 42:
cat -n orders.txt 1 salmon x2
2 tuna x3
3 cod x1Blank lines get a number too. Use -b to number only the lines that have something on them.
-A ('show all') makes invisible characters visible. A tab shows as ^I, the end of every line as $, and other control characters in the same ^ notation. It is the quickest answer to 'this line looks right, so why doesn't it work?':
cat -A config.txtname=kitty $
port=8080^M$
^Iindent=tab$Each line has a problem you can't see in an editor. The first has two spaces before its $, so the value is really kitty plus two spaces. The second ends in ^M, a carriage return. The third starts with a tab, not spaces.
That ^M$ is the classic one. Windows ends each line with a carriage return and a line feed; Linux uses only the line feed. A shell script saved on Windows looks fine, then fails on Linux with errors like $'\r': command not found, because bash reads the carriage return as part of each command. cat -A shows the problem at once, and dos2unix or your editor's line-ending setting fixes it.
-A belongs to GNU cat, the Linux version. macOS ships the BSD version, which has no -A: cat -et shows the same tab and line-end marks there.
cat with no file
Run cat with no file name and it reads standard input instead, which in a terminal is your keyboard. Each line you type is printed back when you press Enter, because cat is still copying its input to its output. Press Ctrl+D at the start of a line to signal the end of the input, and cat exits.
On its own that looks pointless. Add a redirect and it becomes a way to write a file without opening an editor:
cat > notes.txtType your lines, pressing Enter after each, then Ctrl+D. Everything you typed is now in notes.txt. Use >> to add to a file that already exists. Backspace only works on the line you are typing, so once you press Enter that line is saved as it is. This is for quick notes, not for editing.
Scripts use the same idea with a here-document, which feeds a block of text to cat with nobody typing:
cat > config.txt <<EOF
name=kitty
port=8080
EOFWhen cat is the wrong tool
Long files: use less
cat prints everything at once and never pauses. Point it at a log with thousands of lines and they scroll past faster than you can read, leaving only the last screenful. less shows a file one screen at a time:
less app.logSpace moves down a page, b goes back, /error searches forward, n jumps to the next match and q quits. less also opens a large file straight away, because it reads only the part it is showing. When you only need the start or the end of a file, head and tail print its first or last 10 lines.
Searching: give grep the file
You will often see this:
cat app.log | grep errorIt works, but cat adds nothing, because grep can open the file itself:
grep error app.logThe pipe version starts an extra process just to pass the file along. With several files it also loses information: grep error *.log tells you which file each match came from, and cat *.log | grep error can't, because grep only sees one stream. Programmers call this a 'useless use of cat'. It does no harm in a command you type once, but in scripts give the file name to the command directly. grep, sort, wc, head and less all take one. For searching a whole project, ripgrep, from Supercharging Your Terminal, is faster still.
tac: cat backwards
tac is cat spelt backwards, and it prints a file's lines in reverse order, last line first. Logs add new entries at the bottom, so this shows the ten most recent, newest first:
tac app.log | headtac is part of GNU coreutils, so almost every Linux system has it. macOS doesn't: tail -r does the same job there. On Windows, WSL gives you the Linux versions of all of these commands.
Common mistakes
cat a.txt b.txt > a.txtloses what was ina.txt, because the shell empties it for the>beforecatreads it. Write to a new file, then rename it.- Typing
>when you meant>>replaces the file you meant to add to. caton an image or a compiled program sends raw bytes to the terminal, which can leave it showing garbage. Typeresetto fix it, and check what a file is first withfile.- Joined files get no gap between them. If the first doesn't end with a newline, its last line and the next file's first line end up on one line.
Key takeaways
catcopies files to standard output: one file to read it, several to join them in order.>saves the output to a file, replacing what was there;>>adds to the end.-nnumbers lines, and-Ashows tabs (^I), line ends ($) and Windows carriage returns (^M).- With no file,
catreads what you type until Ctrl+D. - Use
lessfor long files, givegrepthe file directly, and usetacto read a file bottom to top.