开发者

In UNIX what "cat file1 > file1 does?"

开发者 https://www.devze.com 2023-01-19 00:13 出处:网络
When the output of a command is redirected to a file, the output file is created or truncated by the shell before the开发者_StackOverflow command is executed, any idea what cat foo > foo does?In all c

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


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.


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.


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


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
0000000
0

精彩评论

暂无评论...
验证码 换一张
取 消