Bash输出重定向问题

10 linux bash

我试图删除除最后一行之外的所有文件行,但是以下命令不起作用,尽管file.txt不为空.

$cat file.txt |tail -1 > file.txt

$cat file.txt
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

Cha*_*ffy 19

从文件通过管道重定向回到同一文件是不安全的; file.txt在设置管道的最后一个阶段之前,如果被shell覆盖tail开始读取第一个阶段最终会出现空输出.

请执行以下操作:

tail -1 file.txt >file.txt.new && mv file.txt.new file.txt
Run Code Online (Sandbox Code Playgroud)

......实际上,不要在生产代码中这样做; 特别是如果您处于安全敏感的环境中并以root身份运行,则以下更合适:

tempfile="$(mktemp file.txt.XXXXXX)"
chown --reference=file.txt -- "$tempfile"
chmod --reference=file.txt -- "$tempfile"
tail -1 file.txt >"$tempfile" && mv -- "$tempfile" file.txt
Run Code Online (Sandbox Code Playgroud)

另一种方法(避免临时文件,除非<<<在您的平台上隐式创建它们)如下:

lastline="$(tail -1 file.txt)"; cat >file.txt <<<"$lastline"
Run Code Online (Sandbox Code Playgroud)

(上面的实现是特定于bash的,但是在echo不能的情况下工作 - 例如,当最后一行包含"--version"时).

最后,可以使用moreutils的海绵:

tail -1 file.txt | sponge file.txt
Run Code Online (Sandbox Code Playgroud)


Chr*_*ris 5

您可以使用sed删除除文件中的最后一行之外的所有行:

sed -i '$!d' file
Run Code Online (Sandbox Code Playgroud)
  • -i告诉sed替换文件到位; 否则,结果将写入STDOUT.
  • $是与文件的最后一行匹配的地址.
  • d是删除命令.在这种情况下,它被否定了!,因此所有与地址匹配的行都将被删除.