这这个问题引发了一个想法,我不确定我是否理解得很好。我知道cat myfile | grep -v mypattern > myfile
由于文件句柄的设置方式,使用管道是不可能或不正确的。但是,为什么我们不能简单地使用cat myfile | grep -v mypattern| tee myfile>/dev/null
就地修改文件呢?有没有失败的简单例子?
具体来说,它是否会导致损坏,或者更多的是不是就地编辑,而是覆盖?
更新问题,如果答案也考虑到这一点,我将不胜感激:
使用有问题吗cat myfile | grep -v mypattern| bash -c 'rm myfile; cat > myfile'
?
答案1
问题是你不能保证哪个先执行。因此,您必须延迟取消链接和写入文件,直到您完全确定该文件已打开以供读取。
这将在写入文件之前将文件缓冲在 RAM 中。
cat foo | perl -e 'undef $/; @out=<>; open WRT,">",shift; print WRT @out' foo
优点:保留foo的权限。如果被中断,你并没有丢失原来的 foo.txt 文件。
缺点:foo 必须适合 RAM。
这将打开文件进行读取、删除并cat
从中删除。它同时等待文件消失,并在文件消失时再进行处理cat
。
(rm foo; cat) < foo | (perl -e 'while(-e "foo"){}'; cat >foo)
优点:短。适用于大于 RAM 的文件。
缺点:一启动foo就没有了。
(mv foo bar; cat) < foo | (perl -e 'while(-e "foo"){}'; cat >foo && rm bar)
优点:适用于大于 RAM 的文件。如果失败,foo 将作为备份保留在 bar 中。
答案2
您不能简单地执行此操作,因为该tee
命令会覆盖文件,使其更短(可能)并消除该cat
命令读取文件中数据的能力。
如果您可以确保诸如tee
打开之类的程序新的文件,和如果 shell 保证cat
首先打开其副本,那么您可以从旧的(实际已删除的)文件复制到新的文件。但有很多假设,但保证很少。
例如,您可能会认为,这cat
将首先启动,然后tee
再启动(当需要捕获数据时)。但是壳启动两者,除非在启动tee
之前等待输入cat
,否则写入可能会失败(因为没有人在等待,并且这些字节无处可去)。让进程等待 aread
比等待 a更容易write
。