从Unix cat重定向文件到自身时的无限循环

时间:2014-09-30 00:55:18

标签: macos unix cat io-redirection bsd

我试图将许可证连接到我构建的源代码顶部。我使用的是GNU Make。在我的一条规则中,我有:

cat src/license.txt build/3d-tags.js > build/3d-tags.js

但这似乎导致无限循环。当我杀死cat命令时,我看到build / 3d-tags一次又一次只是src / license.txt的内容?发生了什么事?我怀疑这两个文件是连在一起的,并且将cat产生的输出重定向回build / 3d-tags.js。我不打算追加。我是OSX的,如果问题与GNU cat vs BSD cat有关。

1 个答案:

答案 0 :(得分:5)

shell启动cat作为子进程。输出重定向(>)由该子进程作为其stdout(文件描述符1)继承。因为子进程必须在创建时继承文件描述符,所以shell必须在启动子进程之前打开输出文件。

因此,shell打开build/3d-tags.js进行写入。此外,由于您未附加(>>),因此会截断文件。请记住,这是在cat发布之前发生的。此时,由于build/3d-tags.js的原始内容已经消失,cat尚未启动,因此无法实现您想要的效果。

然后,当cat启动时,它会打开其参数中指定的文件。它打开它们的时间和顺序并不是非常重要。当然,它会打开它们进行阅读。然后它从src/license.txt读取并写入其标准输出。写作转到build/3d-tags.js。此时,它是该文件中唯一的内容,因为它之前被截断了。

cat然后从build/3d-tags.js读取。它找到刚刚写入的内容,这是cat之前从src/license.txt读取的内容。它将内容写入文件的末尾。然后回去尝试阅读更多内容。当然,它会更多地阅读,因为它只是在文件的末尾写了更多的数据。它读取剩余数据并将其写入文件。等等。

为了让cat按照您的意愿工作(甚至忽略消除build/3d-tags.js内容的shell重定向),它必须在内存中读取并保留{{1}的全部内容},无论它有多大,所以它可以在写完build/3d-tags.js的内容后写出来。

达到你想要的最好的方法可能是这样的:

src/license.txt

即:将两个文件连接到一个新文件;如果成功,将新文件移动到原始文件名(替换原始文件);如果任一步骤失败,删除临时"新"文件,以免留下垃圾。