Terminal – Why Using Cat on Binary Files Messes Up the Terminal

binarycatterminal

If I understand the cat manual correctly:

concatenate files and print on the standard output

cat will take files as argument and print them on standard output.
What I don't get is if I use the command:

cat img.png > copy.png

I will obtain 2 png files identical while if I just

cat img.png  

I have all chance that my terminal get messed up and misinterpret what I type.

  • How's that possible?
  • Binary values are still binary data. Why it does not simply shows a series of 0 and 1 or the interpretation of those binary data in ASCII or whatever the encoding in terminal is?
  • Is this behavior also possible by cating a text file containing strange characters?
  • Should a mechanism to prevent this behavior like try{}catch{} statement should be implemented?

Best Answer

cat concatenates files given as arguments on command line to standard output, it reads bytes at a time an as default does not perform any interpretation of the bytes it reads.

In your first example you are redirecting stdout to a file, that's why you get a new file.

In your second example the bytes are written to the terminal, and it is the terminal which is interpreting sequences of characters as control sequences for the terminal, this is why you get unusual behaviour on your terminal. It has nothing to do with cat as such, cat doesn't know what you are going to do with it's output. You might be sending it through a pipe to another program to interpret/process/print or play "Singing in the rain".

So following the unix philosophy,

do one thing, do one thing only, but do it well

cat should not attempt to second guess what you are trying to do.

edit 1 reply to @kiwy's 1st comment below.

Yes and No, let me explain,

No, if you cat to a terminal, because it (the terminal software) is sending the output to your screen or interpreting control sequences (it is emulating an old piece of hardware ie. a teletype device).

but,

Yes if you cat to a pipe and the program recieving can interpret the characters as commands.

look cat this for an example, cat anyOldShellScript | bash bash will interpret what it gets as commands.

Related Question