惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tenable Blog
D
DataBreaches.Net
S
Secure Thoughts
B
Blog
S
Schneier on Security
Y
Y Combinator Blog
P
Proofpoint News Feed
C
Cybersecurity and Infrastructure Security Agency CISA
C
Cyber Attacks, Cyber Crime and Cyber Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
F
Full Disclosure
Engineering at Meta
Engineering at Meta
L
LangChain Blog
T
Threatpost
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Hacker News
The Hacker News
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
Cyberwarzone
Cyberwarzone
T
The Exploit Database - CXSecurity.com
雷峰网
雷峰网
博客园 - 司徒正美
Help Net Security
Help Net Security
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog
P
Privacy International News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Vulnerabilities – Threatpost
Cisco Talos Blog
Cisco Talos Blog
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Threat Research - Cisco Blogs
Recent Announcements
Recent Announcements
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
H
Heimdal Security Blog
Jina AI
Jina AI
C
Cisco Blogs
Attack and Defense Labs
Attack and Defense Labs
Microsoft Security Blog
Microsoft Security Blog
L
Lohrmann on Cybersecurity
aimingoo的专栏
aimingoo的专栏
D
Docker
I
Intezer
C
Check Point Blog
Cloudbric
Cloudbric
小众软件
小众软件
V2EX - 技术
V2EX - 技术

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派 万字剖析:千问App深度体验报告(2026) - 少数派 在2026年,如何真正防止别人抄袭你的作品 - 少数派 怎么用 50 块搭个 AI 语音助手?我踩了 3 天坑 - 少数派 YeeroAI:让 AI 对话真正成为知识管理的一部分 - 少数派 爬泰山 - 少数派 「旅图显影」 App 更新:这次,我们补上了一点「手感」 - 少数派 假期出门太折磨?我的 23 条经验帮你规划惬意旅行 - 少数派 工作流会变吗 - 少数派 Claude Opus 4.6 怎么用最省钱?我测了 5 种方案 - 少数派 GPT Image 2 让图文并茂不再稀罕 - 少数派 用户侧出发——什么是AI,我要不要学习? - 少数派 找片、转存、整理、播放一条龙!让你的付费网盘值回票价 - 少数派 欢迎试用!日课一问2.0插件 - 少数派 自己做的MDeditor,原本想购买 Typora 试了两次支付不成功,干脆自己做一个 - 少数派 vibe coding了一个 3MB 的小工具,让 ~/Downloads 彻底告别混乱 - 少数派 因为受不了 Mac 的风扇策略,我做了一个风扇控制工具 - 少数派 别只怪模型 - 少数派 Warp 终端的 AI 功能怎么用?我测了一周的体验 - 少数派 AI 写代码老是出 bug?这 5 个配置我后悔没早知道 - 少数派 「新玩意」苹果出相机可能就这样:Sigma BF + 45mm F2.8 DG Contemporary - 少数派 一个面向2030年的AI操作系统是什么样子的:浅谈cola这款有灵魂的Agent - 少数派 别只看写代码 - 少数派 每天解决10个问题,还是一口气攻坚解决400个? - 少数派 AI 交易机器人怎么搭?我用 Claude 跑了一周实盘 - 少数派 Maptoposter Online:把你爱的城市画成艺术海报 - 少数派 Function Calling 怎么用?我测了 3 个模型发现差距真大 - 少数派 Legend Talk:我做了个 AI 圆桌,让 160 位思想家围着你的问题转 - 少数派 如何找到自己的蓝方?在小县城寻找压力测试 - 少数派 语音输入与软件接口|2026年聊AI时,我们都聊些什么(上) - 少数派 混动已经卖爆,纯电又来补刀——钛7闪充版简直“不讲武德” - 少数派 本月玩什么|朋友收藏、识质存在、沙罗周期 - 少数派 为什么要每天坚持输出? - 少数派 Claude API 挂了好几个小时,你的项目有备用方案吗? - 少数派 Function Calling 没你想的复杂——我用它做了个有点用的工具 - 少数派 登录系统立即播放视频或者图片音乐的软件 - 少数派 我为什么创建 FlipHTML5 下载工具 - 少数派 残局没电?多品牌外设电量统一管理软件EasyBluetooth已支持RTSS游戏内显示以及AIDA64 - 少数派 前往通义路的路 - 少数派 太好看了,媲美Sun的个人导航页,NAS部署星云门户 - 少数派 乌黑嘴唇“一键检测”上线了 - 少数派 派早报:Claude AI 接入多个创意软件生态、FILCO 生产方接手品牌等 - 少数派 【更新】BearCLI、Claude 连接器与 MCP 服务器 - 少数派 记了上千条流水,还是看不懂财务?我做了一个让 AI 读懂账本的工作台 - 少数派 MINI R56 升级原厂 Sport 模式 - 少数派 新玩意 | 一棵柠檬树(仿真版) - 少数派 Momenta的“物理AI”野望,需迈过“含摩量”这道关 - 少数派 网页直接投屏控制手机!NAS一键部署PandaScrcpy,流畅丝滑可远程。 - 少数派 众测|邀你一同探索随身 AI 硬件入口 YoooClaw C·ONE - 少数派 2050大会:分享时间是真诚 参会记 - 少数派 iPad 赋能电影创作:国内首部宣纸手绘长片《燃比娃》的幕后故事 - 少数派 AI的审美:我用 8 个大模型给 100 张旅行照片打分 - 少数派 普通人如何破圈?去参加一个本地协会 - 少数派 把极空间的图标全换了,主题DIY全攻略打造你的专属NAS桌面 - 少数派 电子便签墙,帮你实现便签自由 - 少数派 我如何用三个 CLI 工具取代文档创建需求 - 少数派 原来真的有人可以玩一辈子 - 少数派 社区速递 139 | 派友热议三月买了啥、复古单反尼康 Df 体验 - 少数派 06 作品的赏析与评价 - 少数派 TDS REVIEW|索尼 WF-1000XM6 降噪真无线耳机体验 - 少数派 35.98万起售的第二代腾势D9,我看重的不是堆料,而是不凑合 - 少数派 鼠须管 Squirrel 皮肤配置指北 - 少数派 从watch ultra2换到redmi watch6 - 少数派 派早报:阿里巴巴发布视频生成模型 HappyHorse 1.0 等 - 少数派 别迷信1M - 少数派 家人们天塌了!网盘“大封杀”,多个渠道多条路,NAS部署PanHub - 少数派 AI与人勾心斗角!NAS一键部署AI狼人杀,假日休闲必备。 - 少数派 电商必备!Comfyui工作流批量生图插件,一次生成12张!支持Nano banana pro模型 - 少数派 Comfyui工作流配置Gpt-image-2模型教程,0.03/张 - 少数派 OpenClaw第三方APi怎么配置?可使用Gpt-image-2模型 - 少数派 会员社区话题精选 Ep. 103 - 少数派
从零开始,编写一个 HomeBrew 缓存清理脚本 - 少数派
2021-04-01 · via 少数派

Matrix 首页推荐

Matrix 是少数派的写作社区,我们主张分享真实的产品体验,有实用价值的经验与思考。我们会不定期挑选 Matrix 最优质的文章,展示来自用户的最真实的体验和观点。

文章代表作者个人观点,少数派仅对标题和排版略作修改。


如果你正在使用 HomeBrew,并且没有使用过垃圾清理软件对其缓存进行过清理,不如通过 open ~/Library/Caches/Homebrew 命令打开 HomeBrew 缓存目录来看看。HomeBrew 虽然提供了 brew cleanup 工具来回收空间,但它默认只会清理 120 天以前的下载缓存。各种软件包可能堆积在这个目录中,一点一点蚕食 Mac 宝贵的硬盘空间。

在过去,我一直使用 Setapp 中提供的 CleanMyMac X 来清理这些缓存。CleanMyMac X 作为 macOS 垃圾清理软件中的老牌劲旅,可以较好地识别并清理 HomeBrew 留下的垃圾。在退订 Setapp 后,我选择了 Lemon(腾讯柠檬清理)作为 CleanMyMac X 的替代品。Lemon 对国内(尤其是腾讯自家)app 的缓存识别以及清新的 UI 都让我十分满意,但它可以清理的缓存并不及 CleanMyMac X 来得丰富,而其中的一条「漏网之鱼」便是 HomeBrew。

Lemon 无法检测并清理 HomeBrew 缓存
Lemon 无法检测并清理 HomeBrew 缓存

即使是 CleanMyMac X,在清理 HomeBrew 缓存时也稍显不足。

垃圾清理软件的工作原理一般是扫描可能的缓存路径,并且对其中可以清理的目录进行移除。然而,HomeBrew 的缓存目录中除了占据较大空间的软件包之外,还有指令表等其他索引。虽然这些索引可以随时重建,但如果能够精准定位并移除要清理的文件,就能将重建缓存和目录结构的时间节约下来。接下来,我们将编写一个简单的 shell 脚本来完成这个任务。

设计逻辑

我们首先来观察 HomeBrew 缓存目录的结构。HomeBrew 缓存目录下存放了数个索引文件,以及指向所有 HomeBrew Formulae 软件包的符号链接(软链接);Cask 目录则存放了指向所有 HomeBrew Cask 软件包的软链接。在 downloads 目录中,我们可以看到被指向的这些软件包。

HomeBrew 缓存目录结构
HomeBrew 缓存目录结构

软链接,或者叫符号链接,是文件系统中指向其他位置的一种特殊文件。不同于 macOS 中的「替身」和 Windows 中的「快捷方式」,对软链接的访问将直接指向原始文件或目录,因此可以通过软链接访问原始目录内的文件。值得一提的是「访达」会将软链接显示为「替身」,不过二者实际上有很大的不同。

我们发现这个目录下存放了指向两种类型、全部软件包的软链接。除了软链接和软件包之外,其他文件均不属于需要清理的垃圾。因此,我们只需找出所有的软链接,将它们所指的软件包和本身均删除,就能达到精确清理的目的。这样的清理不会影响未完成的下载,因为它们不会被创建软链接。我们将在后面介绍如何清理这类文件。

编写代码

通常,我们建议在 shell 脚本的第一行标明脚本所使用的 shell。macOS Big Sur 的默认 shell 为 zsh,而在这篇文章中我选择了使用更广泛的 bash。二者之间有些许语法差异,但本示例中的脚本不会涉及这些差异。

#!/bin/bash

# 在 shell 脚本中用作单行注释的提示符,系统通过读取位于脚本开头的注释就可以识别脚本所使用的 shell。我们在脚本中可以用 # 来添加一些注释,有时也会被用来隐藏一些无用的代码。

接下来,我们需要找出所有的软链接。我们可以使用系统内置的 find 工具,向它传入 -type l 即可搜索指定目录下的软链接。HomeBrew 缓存目录中的软链接可以用以下命令导出:

find ~/Library/Caches/Homebrew -type l

在 bash 中,我们可以用 $() 来将指令的输出转换为变量。获取到所有软链接后,我们需要对其进行遍历并分别进行处理。bash 提供了 for 语句来进行遍历,在本例中用法如下:

for link in $(find ~/Library/Caches/Homebrew -type l)
do
    # 清理语句
done

在循环体中,符号链接的路径将被保存到局部变量 $link。我们可以用 realpath 工具来直接获取其指向的文件,而不需要自行编写相关的代码。这个工具可以用以下命令安装:

brew install coreutils

不少垃圾清理软件都提供了直接删除和移动到废纸篓的选项。在 macOS 操作系统中提供了 rm 这一很多人都有所耳闻的命令,可以用来直接删除。而如果需要将文件移到废纸篓,我们可以用以下命令安装 trash-cli 工具:

brew install trash-cli

在本例中,所要删除的均是单个文件,而且不存在权限问题,因此调用方式非常简单。

rm <file>       # 直接删除
trash <file>    # 移到废纸篓

结合上述知识点,我们就能实现循环体了。我个人比较推荐将软链接文件直接删除,将软件包移到废纸篓,大家可以根据自己的需要进行选择。对于移到废纸篓的软件包,我们如果需要再次使用可以将其放回 ~/Library/Caches/Homebrew/downloads 目录,HomeBrew 会自动识别并重新建立软链接。完整的脚本文件如下:

#!/bin/bash

for link in $(find ~/Library/Caches/Homebrew -type l)
do
    trash $(realpath $link)
    rm $link
done

其中尤其需要注意的是删除的顺序,必须先处理原始文件、再处理软链接,软链接被删除后将无法定位到原始文件。

保存脚本

我们可以将脚本保存为形如 brew-clean.sh 的脚本文件,这样就可以用 bash brew-clean.sh 来执行它。为了调用更方便,我们可以将其赋予可执行权限,这样就能直接地调用它。我们不妨将其命名为 brew-clean,我们的目标则是通过 brew-clean 这样的命令直接调用这个脚本。

首先,我们可以使用 chmod 命令为 brew-clean 赋予可执行权限。参数 +x 就表示「增加可执行权限」。

chmod +x brew-clean

现在,我们已经可以用 ./brew-clean 的方式来调用它了。为了在任意目录下都可以调用,我们可以将其保存到 /usr/local/bin。这是专门存放用户自行安装的程序的目录。

mv brew-clean /usr/local/bin

以上命令将 brew-clean 文件移动到了 /usr/local/bin。如果你希望复制而非移动,可以将 mv(即 move)替换为 cp(即 copy)。

让我们来试试运行效果:

简单 HomeBrew 缓存清理 demo
简单 HomeBrew 缓存清理 demo

Awesome!

功能拓展

在前两节,我们用短短七行代码就实现了 HomeBrew 缓存清理功能。我将在这一板块抛砖引玉,提出一些可以扩展此脚本的想法和实现方式,大家也可以在评论区里提出自己的 idea。

在脚本中加入 brew cleanup

我们在上文中已经提到,HomeBrew 内置的 brew cleanup 工具可以用来移除历史版本备份,从而释放磁盘空间。如果确有需要,可以在 for 循环前或循环后加入一行 brew cleanup 来调用它。

之所以不推荐在脚本中加入,是因为 brew cleanup 执行十分缓慢(在我的 Mac 上可能长达数分钟),而这个脚本在大多数情况下只需要数秒就能完成下载缓存的清理,直接在脚本中调用 brew cleanup 会使原本轻快的脚本变得笨重。此外,在默认设置下 HomeBrew 每三十天将自动进行一次 cleanup(一般在完成 upgrade 或 install 之后),手动调用比较费时,意义不大。

在运行结束后展示清理结果

brew cleanup 完成后,它会输出清理的文件总数。我们也可以在脚本中实现这一功能,大致的实现如下:

count=0
for link in $(find ~/Library/Caches/Homebrew -type l)
do
    let count++
    # 清理语句
done

echo "Pruned $count symbolic links and $count files from $(realpath ~/Library/Caches/Homebrew)"

在上面这段代码中,我使用了变量 $count 进行计数。shell 默认将变量视为字符串,因此进行数学运算需要使用其他工具或特殊语法,这里使用的是兼容性比较好且较为直观的 let

对 Cask 和 Formulae 进行针对性处理

HomeBrew Cask 软件包一般是 DMG 或是 PKG 格式的安装包。不同于经过特殊封装的 Formulae,Cask 软件包大都是由软件开发商官方发布的,并且可以在任何兼容的机器上很方便地进行安装。我们当然可以单独处理 HomeBrew Cask 软件包,例如将其保留或者移至回收站,而对 Formulae 采取直接删除处理。要达到以上效果,我们可以将以下代码加入到脚本开头:

for link in $(find ~/Library/Caches/Homebrew/Cask -type l)
do
    trash $(realpath $link) # 删除此行以保留 Cask 软件包
    rm $link
done

以上这段代码从利用了 HomeBrew Cask 软链接存放在单独目录的特性,先对其进行处理。这样在执行原有逻辑时,指向 Cask 软件包的链接已经不复存在,所以可以用于单独处理 Formulae 软件包。

清理未完成的下载

在 HomeBrew 中,未完成的下载统一使用了 .incomplete 作为扩展名。它们不会被建立符号连接,因此不能用上文的方式进行处理。对于这类缓存,我们可以直接在下载目录中进行定位并删除。所需命令大致如下:

rm ~/Library/Caches/Homebrew/downloads/*.incomplete

其中,* 是通配符,*.incomplete 即表示该目录下所有名称以 .incomplete 结尾的文件。rmtrash 均支持使用 * 通配符批量删除文件。

总结与延伸

接下来我会将以上提到的所有功能进行整合,晒出一份完整的脚本。大家可以自取所需,以此为基础定制自己的清理脚本:

#!/bin/bash

# 文件计数
file_count=0
link_count=0
incomplete_count=0

# 清理 HomeBrew Cask 下载缓存
for cask_link in $(find ~/Library/Caches/Homebrew/Cask -type l)
do
    # 将 Cask 软件包移至废纸篓
    # let file_count++
    # trash $(realpath $cask_link)
    let link_count++
    rm $link
done

# 清理 HomeBrew 下载缓存
for link in $(find ~/Library/Caches/Homebrew -type l)
do
    let file_count++
    trash $(realpath $link)
    let link_count++
    rm $link
done

# 获取 *.incomplete 文件数量
let incomplete_count=$(ls -l ~/Library/Caches/Homebrew/downloads/*.incomplete | wc -l)
# 清理未完成的下载
rm ~/Library/Caches/Homebrew/downloads/*.incomplete

# 复数输出函数
plural() {
    if [ $1 -gt 1 ]
    then
        echo "$1 $2s"
    else
        echo "$1 $2"
    fi
}

# 输出消息提示
echo "Pruned $(plural $link_count "symbolic link"), $(plural $file_count "file") and $(plural $incomplete_count "incomplete download") from $(realpath ~/Library/Caches/Homebrew)"

# 调用 `brew cleanup`
# echo 'Running `brew cleanup`'
# brew cleanup

在以上的示例中,我使用了一些之前未提到的技巧,例如管道、if 条件分支、自定义函数,以及 lswc 工具。感兴趣的读者可以自行阅读相关的开放教程,例如 鄙社 Linux 101 教程 中的 Shell 脚本 部分。此外,由人民邮电出版社引进的《UNIX/Linux/OS X中的Shell编程(第4版)》是 Shell 编程领域不可多得的佳作,适合各知识水平的读者参考和学习。

拓展阅读:

> 下载少数派 客户端 、关注 少数派公众号 ,了解更妙的数字生活 🍃

> 想申请成为少数派作者?冲!