15

cp a b and cat a > b, what's the difference?

In x86 install script of linux kernel's source tree (arch/x86/boot/install.sh), both are used:

cat $2 > $4/vmlinuz
cp $3 $4/System.map

Why don't they just keep the same format if one is better than the other?

5 Answers 5

18

One more issue comes to my mind where cat vs. cp makes a significant difference:

By definition, cat will expand sparse files, filling in the gaps with "real" zero bytes, while cp at least can be told to preserve the holes.

Sparse files are files where sequences of zero bytes have been replaced by metadata to preserve space. You can test by creating one with dd, and duplicate it with the tools of your choice.

  1. Create a sparse file (changing to /tmp beforehand to avoid trouble - see final note):

    15> cd /tmp
    16> dd if=/dev/null of=sparsetest bs=512b seek=5 
    0+0 records in 
    0+0 records out 
    0 bytes (0 B) copied, 5.9256e-05 s, 0.0 kB/s
    
  2. size it - it should not take any space.

    17> du -sh sparsetest
    0       sparsetest
    
  3. copy it with cp and check size

    18> cp sparsetest sparsecp
    19> du -sh sparsecp
    0       sparsecp
    
  4. now copy it with cat and check size

    20> cat sparsetest > sparsecat
    21> du -sh sparsecat
    1.3M    sparsecat
    
  5. try your preferred tools to check on their behaviour

  6. don't forget to clean up.

Final note of caution: Experiments like these have the inherent chance of rising your fame with your local sysadmin if you're doing them on a filesystem that's part of his backup plan, or critical for the well-being of the system. Depending on his choice of tool for backup, he might end up needing more tape media than he ever considered possible to back up that one 0-byte file which gets expanded to terabytes of zeroes.

Other files which cannot be copied with neither cat nor cp would include device-special files, etc. It depends on your implementation of copying tool if it is able to duplicate the device node, or if it would merrily copy its contents instead.

3
  • 1
    So cp makes a file just like the original, while cat creates a new file with the same content.
    – Qian
    Jan 30, 2012 at 15:29
  • Both tools operate on content, but cp (at least "modern" implementations) is aware of some specialities nowadays, like holes (old implementations of cat will run into that trap). There also are filesystems which are unaware of the concept of sparse files, for example HFS+ (MacOS) or FAT (MSDOS, USB-Sticks, etc), causing them to be blown up to their full size. So there are constellations where cp or cat won't make a difference in practice. Jan 30, 2012 at 15:47
  • 1
    Btw, GNU cp has an option for controlling its behavior on sparse files; like, with --sparse=never specified on the command line, cp is as slow as cat.
    – user309777
    Nov 24, 2019 at 4:46
7

According to Keith's comment, cp preserves some permissions, and cat creates the new file as umask indicates. So $2's permission is not preserved that $4/vmlinuz is pretty clean, while if some strange permission is set on $3, $4/System.map will keep that.

2
  • is that the reason to attribute cat 's fasterness? Jan 29, 2012 at 16:13
  • 2
    Is cat faster?
    – Qian
    Jan 30, 2012 at 13:11
2

Both have equivalent functionality in those two cases, but cp is purely a file operation. "Take this file and make a copy of it over there".

cat, on the other hand, is intended to dump the contents of a file out to the console. "Take this file and display it on the screen" and then have a ninja attack the screen and redirect the output elsewhere.

cp would generally be more efficient, as there's no redirection going only, merely a direct copying of bytes from location A to location B.

cat would be read bytes -> output to console -> intercept output -> redirect to new file.

2
  • 4
    cat won't really output to console -> intercept output -> redirect to new file, output file for cat can be stdout or a normal file, it'll just output to the file, as long as input is not the same as output.
    – Theo
    Jan 29, 2012 at 3:14
  • 6
    cat has nothing to do with the console. Both cat and cp read from the input file and write to the output file. With cat, the output file is opened by the shell, whereas with cp, the output file is opened by cp; this makes no difference in performance. cp may be faster, but for a completely different reason: some implementations of cp try to guess the right chunk size for performance depending on the source and target devices; an implementation of cat wouldn't bother. Jan 29, 2012 at 23:48
2

It's really a matter of preference, IMHO.

There is technically no real difference unless you use the cp command with the -p switch to preserve file ownership/group. Otherwise, it's the same thing functionally. Marc's answer is much more clearly verbose though and accurate.

2
  • 3
    cp without -p does preserve some permissions. For example, if the source file is executable, cp will make the target file executable, but cat will not. Jan 29, 2012 at 2:35
  • Good point! So vmlinuz won't be executable whether $2 is.
    – Theo
    Jan 29, 2012 at 2:38
1

Found cat here and there in some Makefiles/scripts which made me waste time as cat becomes interactive when no input file is given. One can also waste real money on build tools when stalled for a long period.

To illustrate with OP's example:

Let's assume $2 and $3 are empty shell strings (for any bad reason :\ ):

cat $2 > $4/vmlinuz     # waits forever
cp $3 $4/System.map     # returns an error immediately

I now tend to use cp or install over cat when possible.

Interesting answers and comments there, thanks !

1
  • Better yet, always check your inputs! :)
    – Qian
    Aug 14, 2020 at 21:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .