有效地将内存中的文件内容传递给命令行命令

时间:2014-06-22 00:21:13

标签: ruby linux command-line

我有一个ruby脚本,在某个时刻,它有一个内存文件,可能会也可能不会被文件系统中的条目支持。如果文件系统条目不存在,那么天真的解决方案是创建一个临时文件,但这会导致命令行命令将文件重新读入内存。

理想情况下,我希望避免将文件多次读入内存,因为它可能会非常大。

现在,命令行命令确实接受管道输入,所以我认为这可能是一个很好的解决方案,但我找不到任何方法来实现将Ruby File对象的内容管道化为命令行上发生的事情

如果我从错误的方向来到这里,我也会接受其他建议。正在从远程HTTP流中读取未由文件系统条目支持的文件。

1 个答案:

答案 0 :(得分:1)

一种方法是将IO内容读入字符串,然后使用Kernel#open|),IO::popen或{{3创建子进程并将内容写入子进程stdin:

f = the_file_or_io_object
data = f.read

IO::popen('the_command', 'r+') do |io|
  io.write data
  io.close_write
  puts io.read
end

虽然这可以避免将文件写入磁盘(除非它已经与例如tempfile一起),但它涉及将文件内容读入内存然后将它们传递给子进程,因此它们在内存中两次。如果您想避免使用open3(如果您的系统有)和fork

# f as before, no need to read it in this time

pid = fork do
  $stdin.reopen f
  # Now stdin is the file, so when the command is run it will see 
  # it on its stdin
  exec 'the_command'
end

Process.wait pid

如果你在Windows上,你可能没有fork,所以你可以尝试reopen,重定向stdin

pid = spawn 'the_command', :in => f

Process.wait pid