Self Redirection |
January 28th, 2012 |
tech |
Trying to append a file to another, I was surprised when the
terminal just sat there, taking seconds for something that should have
been instant. When I cancelled the operation I found that the file I
was trying to append to hadn't changed and the original file had
ballooned to several megabytes. Looking back, I had redirected a file
to itself:
$ cat file1 >> file1 # should have been file2You can try this yourself, but be prepared to hit Ctrl+C if it isn't instant:
$ echo "abc" > tmp.txt $ cat tmp.txt >> tmp.txtWith BSD
cat
, as I have on my mac, this just sits there,
filling up the disk at around 2MB/s. With GNU cat
, on the
server where I read email, I get:
cat: tmp.txt: input file is output fileIt's even smart enough to detect hardlinks:
$ echo "abc" > tmp.txt $ ln tmp.txt tmp2.txt $ cat tmp.txt >> tmp2.txt cat: tmp.txt: input file is output fileThe code for this in GNU cat, unchanged except for whitespace since at least 1992-11-08 when it was first put under source control, is:
/* Input file can be output file for non-regular files. fstat on pipes returns S_IFSOCK on some systems, S_IFIFO on others, so the checking should not be done for those types, and to allow things like cat < /dev/tty > /dev/tty, checking is not done for device files either. */ if (S_ISREG (stat_buf.st_mode)) { out_dev = stat_buf.st_dev; out_ino = stat_buf.st_ino; } else check_redirection = 0; ... /* Compare the device and i-node numbers of this input file with the corresponding values of the (output file associated with) stdout, and skip this input file if they coincide. Input files cannot be redirected to themselves. */ if (check_redirection && stat_buf.st_dev == out_dev && stat_buf.st_ino == out_ino) { error (0, 0, "%s: input file is output file", infile); exit_stat = 1; goto contin; }The reason hardlinks don't fool
cat
is that it checks the device and inode
values, which all hardlinks to a file will have the same:
$ echo "abc" > tmp.txt $ ln tmp.txt tmp2.txt $ stat tmp.txt | grep Inode Device: 803h/2051dInode: 18645001 Links: 2 $ $ stat tmp2.txt | grep Inode Device: 803h/2051dInode: 18645001 Links: 2
Comment via: google plus, facebook