外壳:GNU BASH
我已经使用以下命令有一段时间了:
echo "$(fmt -w 50 < foo.txt)" > foo.txt
没有任何问题。但是,当我尝试时:
fmt -w 50 < foo.txt > foo.txt
文件 foo.txt 变成空白文件。我认为这是因为 shell 解析的重定向运算符和子 shell 的优先级有关。
搜索 GNU BASH 手册并没有什么成果。有人可以告诉我我是否遗漏了手册中的某些内容吗?我真的很想了解这种行为的原因,以便我可以进一步利用它并了解它可能导致麻烦的任何情况。
答案1
从 Bash 手册来看,3.7.1 简单命令扩展:
当执行一个简单的命令时,shell 从左到右执行以下扩展、赋值和重定向。
命令替换是(2)中发生的扩展之一,重定向发生在(3)中的扩展之后。这与子 shell 没有任何关系,这纯粹是由于 shell 执行操作的顺序造成的。(fmt -w 50 < foo.txt) > foo.txt
也会产生一个空白文件。
答案2
人们可以使用sponge
实用程序:
fmt -w 50 < foo.txt | sponge foo.txt
对原文的注释:
echo "$(fmt -w 50 < foo.txt)" > foo.txt
首先执行的是
fmt
,它的输出被放入细绳,IE双引号中的内容。在fmt
完成之前不会发生任何其他事情。echo
将字符串打印到标准输出。同时 的
echo
输出被重定向>
到foo.txt。
步骤#2 和步骤#3 或多或少同时发生。
原来的代码确实有问题。命令行有长度限制。如果输入foo.txt非常大,特别是大于 的长度getconf ARG_MAX
,该echo
命令将失败或给出不完整的结果。