我有一个很大的 RAR 档案文件夹。文件夹层级结构非常复杂。我想一次性解压整个档案集合。
我有以下一行代码,可以起作用:
find -name "*.rar" -print0 | xargs -0 -n 1 -P 4 unrar x
(请注意,我们并行运行四个线程以加快操作速度。:-))
此命令的问题在于 xargs 在每个 RAR 文件的顶层目录中执行。这意味着所有输出都被转储到顶层文件夹中。
相反,我希望输出与 RAR 存档存在于同一文件夹中。
例子:
Top level
|--FolderA
|----File1.rar
|----File2.rar
|--FolderB
|----File1.rar
|----File2.rar
|----File3.rar
|--FolderC
|----File1.rar
|----File2.rar
每个“File1.rar”文件都包含一个同名文件。因此将它们全部提取到顶层文件夹会导致覆盖问题。
总而言之,我想提取上述层次结构中的所有 RAR 文件。我希望每个 RAR 文件的内容都存在于 RAR 文件所在的文件夹中。
我觉得解决办法是设置工作目录,然后从那里运行 unrar 命令。但是,由于 find 命令给出的是文件名,而不是目录,所以我无法执行类似
| xargs -I{} -n 1 -P 4 cd {} \; unrar x {}
除了编写一个 Perl 或 Python 脚本来包围 unrar 命令并处理将提供的路径拆分成各个部分并执行命令之外,有没有更好的方法来实现这一点?
答案1
存在从路径中提取目录名称 ( dirname
) 和文件名 ( ) 的命令。因此,您可以执行类似以下操作basename
find . -name '*.rar' -print0 | \
xargs -0 -I{} -n1 -P4 /bin/sh -c 'cd "$(dirname {})"; unrar x "$(basename {})"'
据我所知,xargs
不支持更改目录,因此您需要一些中介来执行此操作,因此/bin/sh
。您提到编写一个包装器unrar
,这基本上就是它所做的事情,只是采用单行形式。
答案2
使用 GNU Parallel 它看起来像这样:
find . -name '*.rar' | parallel cd {//} '&&' unrar x {/}
GNU Parallel 是一个通用的并行化器,可以轻松地在同一台机器或通过 ssh 访问的多台机器上并行运行作业。
如果你想在 4 个 CPU 上运行 32 个不同的作业,那么并行化的直接方法是在每个 CPU 上运行 8 个作业:
当一个进程完成时,GNU Parallel 会生成一个新进程 - 保持 CPU 活跃,从而节省时间:
安装
如果您的发行版未包含 GNU Parallel,您可以进行个人安装,此操作无需 root 访问权限。只需 10 秒即可完成,操作如下:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
对于其他安装选项,请参阅http://git.savannah.gnu.org/cgit/parallel.git/tree/README
了解更多
查看更多示例:http://www.gnu.org/software/parallel/man.html
观看介绍视频:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
完成教程:http://www.gnu.org/software/parallel/parallel_tutorial.html
注册电子邮件列表以获取支持:https://lists.gnu.org/mailman/listinfo/parallel
答案3
如果您不需要 选项-P
,xargs
那么您可以使用find -execdir
选项,它类似于-exec
但在执行之前会cd
进入目录。示例:https://stackoverflow.com/questions/16541582/finding-multiple-files-recursively-and-renaming-in-linux/54163971#54163971