Откуда grep знает, что он записывает во входной файл?
если я попытаюсь перенаправить вывод grep
в тот же файл, из которого он читает, например:
$ grep stuff file.txt > file.txt
Я получаю сообщение об ошибке grep: input file 'file.txt' is also the output
. Как это grep
определить это?
4 ответов
согласно исходному коду GNU grep,grep
проверьте i-узлы входа и выхода:
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;
}
на out_stat
заполняется путем вызова fstat
против STDOUT_FILENO
.
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, i.e., 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;
}
попробуйте pipline с cat или tac:
cat file | grep 'searchpattern' > newfile
Это лучшая практика и сокращение для реализации