从Unix cat将文件重定向到其自身时的无限循环 [英] Infinite loop when redirecting file to itself from Unix cat

查看:167
本文介绍了从Unix cat将文件重定向到其自身时的无限循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将许可证连接到内置资源的顶部.我正在使用GNU Make.根据我的规则之一,我有:

I'm trying to concatenate a license to the top of my built sources. I'm use GNU Make. In one of my rules, I have:

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

但是,这似乎导致了无限循环.当我杀死cat命令时,我一次又一次地看到build/3d-tags只是src/license.txt的内容吗?这是怎么回事?我会怀疑这两个文件会串联在一起,并且将cat的输出结果重定向回build/3d-tags.js.我不希望追加.如果问题与GNU cat vs BSD cat有关,我正在OSX上.

But this seems to be causing an infinite loop. When I kill the cat command, I see that build/3d-tags is just the contents of src/license.txt over and over again? What's going on? I would have suspected the two files to be concatenated together, and the resulting ouput from cat to be redirected back into build/3d-tags.js. I'm not looking to append. I'm on OSX, in case the issue is related to GNU cat vs BSD cat.

推荐答案

shell将cat作为子进程启动.该子进程将输出重定向(>)继承为其标准输出(文件描述符1).由于子进程在创建时必须继承文件描述符,因此外壳程序必须在启动子进程之前打开输出文件.

The shell launches cat as a subprocess. The output redirection (>) is inherited by that subprocess as its stdout (file descriptor 1). Because the subprocess has to inherit the file descriptor at its creation, it follows that the shell has to open the output file before launching the subprocess.

因此,shell打开build/3d-tags.js进行写入.此外,由于您没有附加(>>),它会截断文件.请记住,这是在cat尚未启动之前发生的.此时,无法实现所需的目标,因为build/3d-tags.js的原始内容已经消失,并且cat甚至还没有启动.

So, the shell opens build/3d-tags.js for writing. Furthermore, since you're not appending (>>), it truncates the file. Remember, this happens before cat has even been launched. At this point, it's impossible to achieve what you wanted because the original contents of build/3d-tags.js is already gone, and cat hasn't even been launched yet.

然后,启动cat时,它将打开其参数中命名的文件.打开它们的时间和顺序并不是很重要.当然,它将打开它们两者以供阅读.然后,它从src/license.txt读取并写入其stdout.本书写作build/3d-tags.js.此时,它是该文件中的内容,因为它之前已被截断.

Then, when cat is launched, it opens the files named in its arguments. The timing and order in which it opens them isn't terribly important. It opens them both for reading, of course. It then reads from src/license.txt and writes to its stdout. This writing goes to build/3d-tags.js. At this point, it's the only content in that file because it was truncated before.

catbuild/3d-tags.js读取.它找到刚刚写在此处的内容,这就是猫先前从src/license.txt中读取的内容.它将内容写入文件末尾.然后返回并尝试阅读更多内容.当然,它将发现更多要读取的内容,因为它只是在文件末尾写入了更多数据.它读取剩余的数据并将其写入文件.等等.

cat then reads from build/3d-tags.js. It finds the content that was just written there, which is what cat previously read from src/license.txt. It writes that content to the end of the file. It then goes back and tries to read some more. It will, of course, find more to read, because it just wrote more data to the end of the file. It reads this remaining data and writes it to the file. And on and on.

为了使cat能够按您希望的那样工作(即使忽略了shell重定向也消除了build/3d-tags.js的内容),无论大小如何,它都必须读取并保存build/3d-tags.js的全部内容是这样,以便它可以在写入src/license.txt的内容之后将其写入.

In order for cat to work as you hoped (even ignoring the shell redirection obliterating the contents of build/3d-tags.js), it would have to read and keep in memory the entire contents of build/3d-tags.js, no matter how big it was, so that it could write it after it wrote the contents of src/license.txt.

实现所需目标的最佳方法可能是这样的:

Probably the best way to achieve what you want is something like this:

cat src/license.txt build/3d-tags.js > build/3d-tags.js.new && mv build/3d-tags.js.new build/3d-tags.js || rm -f build/3d-tags.js.new

也就是说,将两个文件连接成一个新文件;如果成功,则将新文件移动到原始文件名(替换原始文件名);如果任一步骤失败,请删除临时的新"文件,以免留下垃圾.

That is: concatenate the two files to a new file; if that succeeds, move the new file to the original file name (replacing the original); if either step fails, remove the temporary "new" file so as to not leave junk around.

这篇关于从Unix cat将文件重定向到其自身时的无限循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆