我试图将许可证连接到我构建的源代码顶部。我使用的是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有关。
答案 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
即:将两个文件连接到一个新文件;如果成功,将新文件移动到原始文件名(替换原始文件);如果任一步骤失败,删除临时"新"文件,以免留下垃圾。