学不可以已。——《荀子》

让 unar 当“解压小管家”:一条 find 命令把一堆压缩包全安排了

我之前那篇《mac解压rar》其实已经把 unar 介绍过一遍了:它是那种“你把压缩包丢过去,它就默默把内容掏出来、还不爱吵闹”的类型。
但生活总会给你一点新剧情——

某天我看着一个目录,里面躺着一大堆 .zip / .rar / .7z,像一群等着被“开封”的包裹:
你点一个解一个、解完还得找下一个……解压这件事瞬间从“顺手”变成了“体力活”。

于是我决定:让 unar 不要只做“单兵”,要当“流水线工人”。
这时候,find 登场了——它就像目录里的巡逻队长,能把所有压缩包一个个揪出来,排队交给 unar 挨个处理。

最终我用的是这一条命令:

1
find /Users/achao/Downloads/tmp -type f \( -iname "*.zip" -o -iname "*.rar" -o -iname "*.7z" \) -exec unar {} \;

下面把它掰开揉碎讲清楚:每个参数都干了啥、它们怎么“配合演出”,以及你还能怎么扩展这套思路。


1. unar 简介:沉默但靠谱的“解压执行者”

unar 来自 The Unarchiver 那套工具链(命令行版本)。它最大的气质是:

  • 不需要你指定太多参数,很多时候一条 unar file.rar 就能搞定
  • 支持多种格式(rar/zip/7z/tar…)
  • 输出比较友好,遇到问题也会直接说

你可以把它想成:
“我负责解压,你负责把目标名单递给我。”
而这份“目标名单”,就由 find 来生成。


2. 这条 find 命令到底在说什么?

先把整句话翻译成人话:

/Users/achao/Downloads/tmp 这个目录里,找出所有普通文件;
如果文件名(不区分大小写)匹配 *.zip*.rar*.7z
就对每一个文件执行一次 unar 文件路径

现在开始逐段拆解。


3. find /Users/achao/Downloads/tmp:巡逻队长的“辖区”

1
find /Users/achao/Downloads/tmp
  • find:从某个目录出发,递归向下遍历
  • /Users/achao/Downloads/tmp:起点目录,也就是它的巡逻范围

find 的性格很认真:
你让它查一个目录,它就会一路向下,把子目录、子子目录都翻出来(除非你阻止它)。


4. -type f:只抓“文件”,不抓“目录”

1
-type f

-typefind 的筛选器之一:

  • -type f:普通文件(regular file)
  • 还有常见的:
    • -type d:目录(directory)
    • -type l:符号链接(symlink)

这里用 -type f 的意义是:
只把真正的压缩包文件交给 unar,不要把目录名也拿去解压(那会很尴尬)。

你可以想象 unar 在旁边看着目录名会说:
“你给我这个干嘛,我又不是挖掘机。”


5. \( ... \):把多个条件“括”成一组

1
\( -iname "*.zip" -o -iname "*.rar" -o -iname "*.7z" \)

这一段是整条命令里最像“语法题”的部分,但它其实就是:

  • \(\):分组(grouping)
  • 为什么要加反斜杠 \
    • 因为在 shell 里,( ) 可能有特殊意义
    • find 也把它们当表达式语法
    • \( \) 更稳,避免被 shell 提前误解

这就像你在跟 find 说:
“接下来这几条规则是一个小团队,必须一起算。”

如果你不分组,-o(OR)会影响整个表达式的结合方式,结果可能跟你想的不一样。
分组能让逻辑变得明确:这三种后缀算一类


6. -iname:不区分大小写的“文件名匹配”

1
-iname "*.zip"
  • -name:按文件名匹配(区分大小写)
  • -iname:按文件名匹配(不区分大小写)

为什么我更偏向 -iname

因为压缩包经常不讲武德,比如:

  • A.ZIP
  • backup.Rar
  • movie.7Z

-iname 会像个脾气好的识别官:
“大小写不重要,你是 zip 就行。”

模式 "*.zip" 里:

  • * 表示任意长度字符
  • .zip 是后缀

注意这个引号也很重要:
它防止 shell 在当前目录先帮你展开 *.zip,让 find 能正确收到模式字符串。


7. -o:三位候选人,只要“任意一个满足”就放行

1
-o

-o 就是逻辑 OR。

整段条件:

  • -iname "*.zip"
  • -iname "*.rar"
  • -iname "*.7z"

任意匹配一个,就算通过筛选。

你可以把 -o 想成一个热心路人:
“只要你会三种语言之一,我就放你进场。”


8. -exec unar {} \;:对每个结果执行一次 unar

这一段是“动作”,也是最爽的地方:

1
-exec unar {} \;

逐个解释:

8.1 -exec:找到之后,立刻执行命令

-exec 的意思是:
对每一个匹配到的文件,执行你指定���命令

find 一边走一边找,一边找一边干活,属于“发现即处理”。

8.2 unar:交给谁处理?

这里当然是交给 unar 这位解压小管家。

8.3 {}:占位符,代表当前找到的那个文件

{} 会被替换成匹配到的文件路径,比如:

  • /Users/achao/Downloads/tmp/a.rar
  • /Users/achao/Downloads/tmp/sub/b.7z

你可以把 {} 理解为 find 给 unar 递的“工单”:

“喏,这个文件,去解一下。”

8.4 \;:-exec 的“句号”

-exec ... \; 这整个结构需要以 ; 结束。
同样,; 在 shell 里也很敏感,所以写成 \; 更安全。

这就像你说完一句话要有句号,否则 find 会盯着你:
“你命令还没说完吧?我怎么执行?”


9. 运行后会发生什么?unar 会把东西解到哪里?

一般情况下,unar 会在压缩包所在目录解压,可能会创建同名文件夹(取决于压缩包内容结构)。
也就是说,如果压缩包散落在不同子目录里,就会在各自位置解开——非常符合“就地处理”的工作风格。

如果你希望统一解到某个目录,可以考虑让 unar 带输出目录参数(不同版本参数略有差异),或者改用“先复制到某个地方再解压”的策略。我的场景是:压缩包在哪就解到哪,最省心。


10. 小升级:先“演练”再“开干”

在真正批量解压之前,我喜欢让 find 先把名单打印出来,确保筛选条件没写错:

1
find /Users/achao/Downloads/tmp -type f \( -iname "*.zip" -o -iname "*.rar" -o -iname "*.7z" \)

它会输出一堆文件路径,相当于让巡逻队长把名单给你过目:
“这些人我准备抓了,你看对不对?”

名单没问题,再加上 -exec unar 开干。


11. 更快一点:用 + 批量传参(可选)

你现在的命令是每个文件执行一次 unar:

1
-exec unar {} \;

还有一种写法:

1
-exec unar {} +

区别:

  • \;:每匹配一个文件就运行一次命令(一次一个)
  • +:尽可能把多个匹配结果拼在一起,少启动几次进程(一次多个)

不过要注意:某些命令对“同时传多个文件”支持不一定一致。
如果你不确定 unar 对多参数是否符合预期,就继续用 \;,稳。


12. 同一套思路还能干什么?举两个顺手的例子

既然 find 能把目标一个个挑出来交给某个工具,那它就不只是“解压流水线”,还是“批处理万能流水线”。

12.1 找到所有 .log 并按时间删除(清理工模式)

比如清理 7 天前的日志文件:

1
find /Users/achao/Downloads/tmp -type f -iname "*.log" -mtime +7 -delete

这里 find 变身保洁队长:
“超过 7 天的旧日志?走你。”

12.2 找到所有 .zip,先看看大小再决定要不要解(审计模式)

1
find /Users/achao/Downloads/tmp -type f -iname "*.zip" -exec ls -lh {} \;

它会对每个 zip 执行一次 ls -lh,让你看到大小、时间等信息。
这时候 -exec 的搭档从 unar 换成了 ls,逻辑完全复用。


13. 回到最初的问题:为什么这条命令能救命?

因为它把“重复劳动”拆成了两个角色:

  • find:负责在目录里把目标找出来(不怕深、不怕多、不怕乱)
  • unar:负责把每个目标干净利落地解出来(不跟你废话)

当压缩包从“偶尔出现”变成“成堆出现”时,
手动解压就像你亲自去一个个敲门收快递;
而这条命令,是你直接叫了个快递站的分拣系统。

最后再贴一次主角登场的台词:

1
find /Users/achao/Downloads/tmp -type f \( -iname "*.zip" -o -iname "*.rar" -o -iname "*.7z" \) -exec unar {} \;

愿你的压缩包们,从此不再排队等你点鼠标;
而是被 unar 这个“沉默的解压小管家”,在 find 的带领下,有序、快速、一个不落地安排到位。