grep如何知道它正在写入input文件?

如果我尝试将grep的输出redirect到正在读取的文件,如下所示:

 $ grep stuff file.txt > file.txt 

我得到错误信息grep: input file 'file.txt' is also the outputgrep如何判断呢?

根据GNU的grep源代码, grep检查输入和输出的i-nodes:

  if (!out_quiet && list_files == 0 && 1 < max_count && S_ISREG (out_stat.st_mode) && out_stat.st_ino && SAME_INODE (st, out_stat)) /* <------------------ */ { if (! suppress_errors) error (0, 0, _("input file %s is also the output"), quote (filename)); errseen = 1; goto closeout; } 

通过调用fstatout_stat来填充fstat

  if (fstat (STDOUT_FILENO, &tmp_stat) == 0 && S_ISREG (tmp_stat.st_mode)) out_stat = tmp_stat; 

查看源代码 – 可以看到它检查了这种情况(该文件已经被grep读取)并报告,请参阅下面的SAME_INODE检查:

  /* If there is a regular file on stdout and the current file refers to the same i-node, we have to report the problem and skip it. Otherwise when matching lines from some other input reach the disk before we open this file, we can end up reading and matching those lines and appending them to the file from which we're reading. Then we'd have what appears to be an infinite loop that'd terminate only upon filling the output file system or reaching a quota. However, there is no risk of an infinite loop if grep is generating no output, ie, with --silent, --quiet, -q. Similarly, with any of these: --max-count=N (-m) (for N >= 2) --files-with-matches (-l) --files-without-match (-L) there is no risk of trouble. For --max-count=1, grep stops after printing the first match, so there is no risk of malfunction. But even --max-count=2, with input==output, while there is no risk of infloop, there is a race condition that could result in "alternate" output. */ if (!out_quiet && list_files == 0 && 1 < max_count && S_ISREG (out_stat.st_mode) && out_stat.st_ino && SAME_INODE (st, out_stat)) { if (! suppress_errors) error (0, 0, _("input file %s is also the output"), quote (filename)); errseen = true; goto closeout; } 

这里是如何写回一些文件:

 grep stuff file.txt > tmp && mv tmp file.txt 

尝试与猫或tac的管道:

  cat file | grep 'searchpattern' > newfile 

这是最好的实践和实现的短暂