【发布时间】:2020-07-26 09:00:32
【问题描述】:
我在 Windows 10 上的 Ruby 脚本中使用 Info-ZIP 实用程序来解压缩存档、编辑内容并重新压缩它。该脚本旨在遍历一批档案,并删除提取内容时创建的临时文件夹。但是,该文件夹并未被删除。例如:
archives.each { |archive|
system("unzip.exe -o archive -d temp")
[...]
system("zip.exe -X0q archive .")
FileUtils.rm_rf "temp"
}
这在 Mac 上总是可以正常工作(使用相同的脚本,结合 zip/unzip 命令),但是,在 Windows 中,我无法删除临时文件夹。解压和压缩过程正常,但不会删除“temp”文件夹。这会导致解压缩实用程序抛出相同的错误:error: cannot delete old temp/[file] 对于文件夹中存在的每个文件。
我尝试过使用system("del /Q temp"),它会引发Could Not Find: C:\[...]\temp 错误,即使该目录确实存在。我尝试了system("rmdir /s /q temp"),它引发了另一个错误:The process cannot access the file because it is being used by another process. 不过,使用此文件的唯一“进程”是脚本本身。
脚本运行完成后,如果我之后运行FileUtils.rm_rf "temp",它就会运行,并成功删除目录。但是,我需要在每次迭代之后并在相同的原始脚本中完成此操作,以便在执行结束时正确覆盖和删除目录,而不会在命令提示符中出现任何错误或警告。
还有其他方法可以强制删除这个文件夹吗?
更新:在对脚本的不同部分进行了更多测试后,我能够找到问题的确切根源。所以所有的档案都包含 XHTML 文件。该脚本在某些情况下需要复制档案,并且复制的档案的内容被修改。是否需要复制取决于 XHTML 文件中是否存在某些标记。该脚本使用 Nokogiri 解析内容。似乎是通过 Nokogiri 解析的方法引发了这个问题。简化代码:
FileUtils.cp(original_archive,new_archive)
unzip_archive(new_archive) # a function to contain the unzipping steps
Dir.glob("temp/**/*.{html,xhtml}").each { |page|
contents = Nokogiri::XML(open(page))
}
zip_archive(new_archive)
在此示例中,实际上没有发生任何事情,但 Nokogiri::XML(open(page)) 的存在足以触发错误。通过 Nokogiri 打开的每个页面都会发生这种情况。因此,如果我将其更改为仅一页:
contents = Nokogiri::XML(open(Dir.glob("temp/**/one_page.xhtml")))
然后FileUtils.rm_rf 'temp' 成功删除了临时文件夹中的文件除了 为one_page.xhtml,这会引发“无法删除”错误。
有没有办法绕过这个问题,这样我仍然可以在我的 Ruby 脚本中使用 Nokogiri,但不会让脚本认为 Nokogiri“进程”仍在运行?这是 Windows 特有的,因为在 Mac 上没有遇到此类问题。
【问题讨论】:
-
zip 进程是否在 Windows 的后台运行?好像是这样的。如果您在尝试删除之前
sleep的时间足够长怎么办? -
使用
Process.wait(Process.spawn('zip.exe -X0q archive .'))等待 zip 命令退出。更多信息请访问ruby-doc.org/core-2.7.0/Process.html#method-c-spawn。无权访问 Windows,因此我无法验证它在该平台上是否可以正常工作,因此不作为答案发布。 -
Process.wait确保在子进程退出之前控制权不会传递回父进程,因此您可以非常安全地依赖它。如果您不生成任何进程而是手动创建temp和单个文件,然后尝试使用FileUtils.rm_rf 'temp'删除它们会发生什么? -
这能回答你的问题吗? Ruby: Ensuring files are closed when reference is held by a different object?(注意接受答案的最后一行:Nokogiri 不会关闭打开的文件)
-
在 Ruby 中没有直接等效项:ruby-doc.org/core-2.4.4/File.html 您是否从两个答案中同时尝试了
File.open和File.read?
标签: ruby windows zip nokogiri unzip