Overview

What a great name for a tool. Funny enough, there is a dog command, but it’s not installed by default. The original cat came with Unix version 1 in November 1971, and it replaced an older command called pr. Believe it or not, chances are, the pr command is on your machine today! That’s a new one on me. The pr command has a different output format than cat, making it a bit “prettier” because it offers a pagination filter. Anyway, back to cat. It’s short for concatenate. The GNU version of cat was written by written by Richard Stallman (the head of the GNU Project) and Torbjorn Granlund. cat is great for viewing short, single files, and that’s what I believe most people use it for. But there is so much more. Okay not soooo much more, but we’ll dive into some of the extra features because when used with single or multiple files it has some flags that can modify the output.

Let’s take a look at the man page to see what this program is all about.

concatenate files and print on the standard output – man 1 cat

Pretty straight forward, eh?

Usage

The basic usage for cat is as follows.

cat file
And the contents of the file will be printed to Standard OUT. Great for text files. Try this on a binary file, let me know how that goes ^_^ If you want to find all the ASCII in a binary, you can use the strings command, but I’ll leave that for another article.

There are some differences between the GNU version and the BSD version on macOS, but I will be trying to focus on common functionality between both of them.

option description
-n number the lines of the output
-t show non printing characters. This would show characters like ^M and would display tab characters as ^I as well as a few others
-e display $ at end of each line

Didn’t think cat could do some of this stuff did ya? Now that we have an idea of what it can do, let’s try a few examples.

Examples

We need a few files to work with. We’re going to take the Go programming LICENSE file. The LICENSE file is pretty short, about 30 lines, and it will be split it into a three separate files, each containing about 10 lines. Copy paste the commands below.

curl -sL https://raw.githubusercontent.com/golang/go/master/LICENSE | split -l 10 -a 1 - golang-licence-
ls golang-*
golang-licence-a golang-licence-b golang-licence-c

Starting with the basics. Print the contents of the first file to the terminal.

cat golang-licence-a
Copyright (c) 2009 The Go Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

   * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer

Next, we can use cat for what it does best and concatenate all the files together so we can view the document as a whole. Notice that there are no headers for each file; no break to distinguish where each file starts or stops; no obtrusions in any way. It prints all content cleanly to the screen.

cat golang-licence-a golang-licence-b golang-licence-c
Copyright (c) 2009 The Go Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

   * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
   * Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

With some of the basic stuff out of the way, let’s use some options to modify the output behaviour. Use the -n option to print out line numbers.

NOTE: On macOS, when you run the following command, you will notice that the line number counter resets after the first file is finished. If you’re not a fan of that, I recommend installing the GNU coreutils with brew coreutils, and then using gcat.

cat -n golang-licence-a golang-licence-b
     1	Copyright (c) 2009 The Go Authors. All rights reserved.
     2
     3	Redistribution and use in source and binary forms, with or without
     4	modification, are permitted provided that the following conditions are
     5	met:
     6
     7	   * Redistributions of source code must retain the above copyright
     8	notice, this list of conditions and the following disclaimer.
     9	   * Redistributions in binary form must reproduce the above
    10	copyright notice, this list of conditions and the following disclaimer
    11	in the documentation and/or other materials provided with the
    12	distribution.
    13	   * Neither the name of Google Inc. nor the names of its
    14	contributors may be used to endorse or promote products derived from
    15	this software without specific prior written permission.
    16
    17	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    18	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    19	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    20	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

To see where each line ends, use the -e option to display a $ at the end of each line.

cat -e golang-licence-a
Copyright (c) 2009 The Go Authors. All rights reserved.$
$
Redistribution and use in source and binary forms, with or without$
modification, are permitted provided that the following conditions are$
met:$
$
   * Redistributions of source code must retain the above copyright$
notice, this list of conditions and the following disclaimer.$
   * Redistributions in binary form must reproduce the above$
copyright notice, this list of conditions and the following disclaimer$

We can use cat to combine all our files into one LICENSE file again, using redirects. But I want the line numbers to appear in the output as well.

cat -n golang-licence-a golang-licence-b golang-licence-c > LICENSE

You can also use cat to create a new file! To terminate the command once you’re finished press CTRL-C or RETURN and then CTRL-D.

cat > hello.txt
why hello there!
how are you today?
meh...

We can take this a step further and create a new file with cat while also using a heredoc. No need for CTRL-C, as the command will quit once it reads EOF. After you’ve created new-file.txt, use cat to view its contents.

cat << EOF > new-file.txt
this is a new file
what whaaaaaat!?
EOF

Bonus Command!

If you’ve loved cat so much but thought I sure wish I could output that file in reverse then I introduce to you tac (see what they did there? its cat but backwards, hehe).

STOP CAT ABUSE

I’d like to take a moment and talk about cat abuse. This is something I know I am guilty of from time to time, but I am trying to make an effort to change my ways.

You’ve probably seen a few examples like this on other websites:

cat "system.log" | head -n 5
cat my-list.txt | sort -r
cat /etc/passwd | grep root

What’s wrong with these commands? Well, every one of the above commands (and there are many more) take filenames as an argument and can be used the same way without using cat If for some reason you prefer to go the STDIN route, use the file redirection <. That’s exactly whats happening when you use cat file | except now you’ve started another process.

Take a look at examples above once again. Here they are without using cat, producing the same results.

head -n 5 "system.log"
sort -r < my-list.txt
grep root /etc/passwd

Conclusion

I hope you learned something new about cat and that it can do a little more than just display the contents of a file on the screen, and remember, stop cat abuse. Cheers.

References