Take the 2-minute tour ×

When the output of a command is redirected to a file, the output file is created or truncated by the shell before the command is executed, any idea what cat foo > foo does?

share|improve this question
I suspect this would be a very good test of the behavior of the shell. –  Stefan Mai Oct 8 '10 at 4:48
add comment

4 Answers

up vote 9 down vote accepted

In all cases, the file is truncated. That’s because redirection is handled by the shell, which opens the file for writing before invoking the command.

cat foo > foo

The shell truncates and opens foo for writing, sets stdout to the file, and then exec’s ["cat", "foo"].

GNU cat is smart and refuses to redirect a file to itself. It does this by checking the device/inode pair on the input and output file descriptors; you can read the wonderful low-level details in src/cat.c. It prints a message and quits.

BSD cat doesn’t have such a safety, but since the file has already been truncated, there is nothing to read, nothing to write, and it will halt.

You can spice things up a bit by appending instead of truncating.

echo hello > foo
cat foo >> foo

Now everything is the same except the shell opens the file for appending instead of truncating it.

GNU cat sees what you’re doing and stops; the file is untouched.

BSD cat goes into a loop and appends the file to itself until your disk fills up.

share|improve this answer
add comment

On Fedora 13 this is what I see

cat foo > foo
cat: foo: input file is output file

If foo contained anything previously, it is gone.

share|improve this answer
add comment

The file is truncated first and then read, so this command would truncate the file.

When I tried to execute it I got this warning:

cat: test.txt: input file is output file

share|improve this answer
What platform's cat do you have? cat foo > foo results in an empty foo file for me. –  birryree Oct 8 '10 at 4:51
add comment

Shell will truncate, cat apparently checks a named parm, but will not check against stdin as below and always succeeds:

$ uname -a
Linux bar 2.6.18-164.15.1.el5PAE #1 SMP Wed Mar 17 12:14:29 EDT 2010 i686 i686 i386 GNU/Linux
$ dd if=/dev/urandom of=foo bs=1024 count=4
4+0 records in
4+0 records out
4096 bytes (4.1 kB) copied, 0.00334456 seconds, 1.2 MB/s
$ od -c foo |head -2
0000000   U 371 003   z 224 334   z   K 236 221   k       <   c 256   !
0000020   %   % 256   V   \ 005   , 254   X 202 330 004 222   " 037 226
$ cat <foo >foo && od -c foo
share|improve this answer
Thanks for all of your replies. they were every helpful. –  HelloWorld Oct 8 '10 at 5:48
add comment

Your Answer


