我有一个 shell 脚本,用于unzip
在 shell 内将一个非常大的文件从远程目录获取到本地目录。这个操作需要相当长的时间,大约20-30分钟。
#!/bin/sh
…
unzip RemoteHostNFSDirectory -d LocalHostDirectory > output.log
(这是一个 6.2 GB 的文件)。
如何将上述命令嵌入到进度或沙漏栏中,以便用户不会认为它只是挂起并且一旦提取到本地目录成功完成。我可以打印成功或失败的错误。
(我是 shell 新手,如有不便,请谅解。)
答案1
初步说明
显示“进度条或沙漏栏,这样用户就不会认为它只是挂起”,无论是否unzip
未挂起都会非常容易。在这个答案中,我假设您不想误导用户。答案试图显示 的进展unzip
,而不仅仅是一个虚假的指标。
最直接的方法
如果你的unzip
可以从标准输入读取并且您想要提取整个存档,然后在读取存档时测量进度:
< /path/to/archive.zip pv | unzip -
pv
可以被任何显示进度信息并传递数据的工具替代。
其他通用方法
如果您unzip
无法从标准输入读取数据,但您确定存档中只有一个文件,并且您知道要用于提取的文件的名称,则提取到标准输出并传递pv
以获取进度指示器:
unzip -p /path/to/archive.zip | pv > /extracted/name
如果存档中可能有更多文件,那么您需要指定要提取的单个文件:
unzip -p /path/to/archive.zip internal/path/to/compressed/file | pv > /extracted/name
使用单个文件提取多个文件unzip -p
会将它们连接到/extracted/name
.要提取多个文件,请运行unzip
多次,每次都重定向到不同的路径名。
如果您不知道内部名称,那么您需要事先解析unzip -l
或unzip -v
。通过这种方式,如果您想将其与pv -s
.我承认我不知道这些格式总体上有多稳定和可解析(明确)。
有了unzip -p
你将不会得到任何日志unzip
。依赖其退出状态。如果您需要某种日志,那么 shell 脚本本身应该写入它。脚本必须至少知道/extracted/name
,因此它至少可以记录此。
保险丝?
我期待任何基于FUSE的解决方案允许您使用任何能够复制常规文件的工具。进度条可以取决于工具。该命令可能很简单:
pv /mountpoint/internal/path/to/compressed/file > /extracted/name
这不一定对你有帮助。我测试过fuse-zip
。看起来它会在实际的复制工具开始工作之前提取(到临时文件或内存中,等等)。所以实际的提取仍然没有任何进度指示;所选工具只能指示稍后复制已提取的文件。缓存“非常大的文件”有其自身的问题,我不确定该工具是否以及如何尝试解决这些问题。无关紧要,因为fuse-zip
无论如何都无法解决您原来的问题。
我也测试过archivemount
。进度条pv
立即开始,但整个设置速度慢得令人痛苦。我发现archivemount
即使读取过程按顺序读取,存档内也会来回跳转(查找)。对于您的“非常大的文件”来说,这可能是不切实际的。或许一些调整是可能的,也许我错过了它们。
欺骗pv
一个聪明但有点麻烦的方法是pv -d
:
unzip /path/to/archive.zip > output.log &
pv -d "$!"
wait "$!"
该方法应该可以让“用户不认为它只是挂起”,尽管在其基本形式中它会向用户展示比您可能想要的更多内容。某些选项pv
甚至“手动”解析/proc/$!/fd
和/proc/$!/fdinfo
不解析pv
可能会有所帮助。
unzip
在后台工作将无法轻松获得用户的响应,因此请考虑unzip -o
(谨慎)。
pv
终止后会终止,所以如果你想严格等待unzip
就不需要。是否可以返回退出状态。wait
wait "$!"
unzip