Subject: bug#17384: "bug" in the Unix "cat" command

From: Bernhard Voelker <[email-masked]>
Date: Thu, 01 May 2014 22:52:52 +0200

tags 17384 + moreinfo
thanks

On 05/01/2014 08:50 PM, Peter Rowat wrote:
> Hello Gnu folks,
> 
>   I had 3 files  matching “isi.*.02p0:
> 
> wc -l isi.*.02p0
>    20000 isi.R.0400.02p0
>    15500 isi.Ra.0400.02p0
>    15600 isi.Rb.0400.02p0
>    51100 total
> 
> I wanted to combine them into one big file, while knowing *not* to cat into a file with same name as an original file,
>  I did this:
> 
> cat isi.*.02p0 >isi.Rall.0400.02p0
> 
> 
> But it never returned!! 
> By the time I hit Ctrl-C, the file isi.Rall.0400.02p0 was already 3000 times bigger than the biggest of the original files.
> 
> A hidden loop was made. 
> 
> Because the destination file was created before concatenation started, it became a match for the
> pattern "isi.*.02p0”.
> 
> It might be worth adding a warning about this on the  cat man-page ??

Thanks for the bug report.

However I cannot reproduce the problem.
On my system (openSUSE-13.1), the output file is created with exactly
the 51100 lines as expected:

  $ seq 20000 > isi.R.0400.02p0
  $ seq 15500 > isi.Ra.0400.02p0
  $ seq 15600 > isi.Rb.0400.02p0
  $ wc -l isi.*.02p0
   20000 isi.R.0400.02p0
   15500 isi.Ra.0400.02p0
   15600 isi.Rb.0400.02p0
   51100 total
  $ src/cat isi.*.02p0 >isi.Rall.0400.02p0
  $ wc -l isi.*.02p0
   20000 isi.R.0400.02p0
   15500 isi.Ra.0400.02p0
   51100 isi.Rall.0400.02p0
   15600 isi.Rb.0400.02p0
  102200 total

If the output file had previously existed (so that the file name
globbing would let it match the pattern), then cat(1) would have
complained:

  $ src/cat isi.*.02p0 >isi.Rall.0400.02p0
  src/cat: isi.Rall.0400.02p0: input file is output file

That means that on your system
a) the shell opened the output file before doing the pattern matching,
and b) cat(1) was unable to detect that the output file is the same
as the input file.
As that check is included in GNU coreutils' cat(1) since day one,
this issue is not a matter of an outdated version of cat(1).

What system are you using (OS, file system type, shell, shell version,
and finally 'cat --version')?
Can you confirm that the previously non-existing output file was
matched by the pattern using "set -x" before issuing the command?

When the output file did not previously exist:

  $ ( set -x; src/cat isi.*.02p0 >isi.Rall.0400.02p0 )
  + src/cat isi.R.0400.02p0 isi.Ra.0400.02p0 isi.Rb.0400.02p0

When the output file already exists:

  $ ( set -x; src/cat isi.*.02p0 >isi.Rall.0400.02p0 )
  + src/cat isi.R.0400.02p0 isi.Ra.0400.02p0 isi.Rall.0400.02p0 isi.Rb.0400.02p0
  src/cat: isi.Rall.0400.02p0: input file is output file

Thanks & have a nice day,
Berny