问题猛砸输出重定向 [英] Problem with Bash output redirection
问题描述
我试图删除除最后一行一个文件的所有行,但下面的命令没有工作,虽然file.txt的不是空的。
I was trying to remove all the lines of a file except the last line but the following command did not work, although file.txt is not empty.
$cat file.txt |tail -1 > file.txt
$cat file.txt
为什么会这样呢?
Why is it so?
推荐答案
从通过管道回到同一文件的文件重定向是不安全的;如果 file.txt的
之前设置管道的最后阶段时,由外壳覆盖,尾巴
开始读取关闭第一阶段,你最终空的输出。
Redirecting from a file through a pipeline back to the same file is unsafe; if file.txt
is overwritten by the shell when setting up the last stage of the pipeline before tail
starts reading off the first stage, you end up with empty output.
执行以下操作来代替:
tail -1 file.txt >file.txt.new && mv file.txt.new file.txt
......嗯,其实,不这样做,在生产中code;特别是如果你在一个安全敏感的环境,并以root权限运行,以下是比较合适的:
...well, actually, don't do that in production code; particularly if you're in a security-sensitive environment and running as root, the following is more appropriate:
tempfile="$(mktemp file.txt.XXXXXX)"
chown --reference=file.txt -- "$tempfile"
chmod --reference=file.txt -- "$tempfile"
tail -1 file.txt >"$tempfile" && mv -- "$tempfile" file.txt
另一种方法(避免临时文件,除非<<<
隐式地创建他们你的平台上)如下:
Another approach (avoiding temporary files, unless <<<
implicitly creates them on your platform) is the following:
lastline="$(tail -1 file.txt)"; cat >file.txt <<<"$lastline"
(以上实施bash的特异性,但是在回波不情况下工作 - 例如当最后一行包含--version,例如)。
(The above implementation is bash-specific, but works in cases where echo does not -- such as when the last line contains "--version", for instance).
最后,可以使用来自 moreutils海绵:
tail -1 file.txt | sponge file.txt
这篇关于问题猛砸输出重定向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!