在Unix/Linux生态中,ls命令无疑是使用频率最高的工具之一。它简单、直观,但背后的GNU coreutils版本经过多年迭代,二进制体积已膨胀至数百KB,依赖库更是复杂。近日,Hacker News上出现了一则名为“Show HN: 18KB ls alternative in no_std rust and Libc”的帖子,引起开发者社区热议。一位名为“ls-mini”的开发者用Rust的no_std模式结合Libc接口,打造了一个仅有18KB的ls替代品,在“极致精简”与“核心功能”之间找到了一个令人惊讶的平衡点。

一个18KB的ls能做什么?

据项目README介绍,这个名为xls(暂名)的工具支持最基本的目录列表功能: xlsxls -a(列出包括隐藏文件)、xls -l(长格式,显示权限、所有者、大小、修改时间)、xls -h(人类可读大小)。输出风格与标准ls一致,支持ANSI颜色,但去除了几乎所有的“非必需”特性——没有自动对齐(依赖外部宽字符计算)、没有排序选项、不支持高亮、没有递归-R,更没有--color=auto的复杂环境检测。开发者明确表示:“它只做一件事,并且做得足够快。如果你需要花哨的滤镜或交互式分页,请使用exa或lsd。”

这种“减法”哲学直接映射到了二进制体积上:编译后的静态链接二进制文件仅18KB(x86-64 Linux),无任何外部依赖(除了运行时必须的libc)。相比之下,GNU ls(来自coreutils 9.4)静态编译后约420KB,exa(Rust实现)约1.2MB,而lsd(Rust实现)约800KB。18KB,直降一个数量级。

no_std + Libc:在裸机与系统调用之间走钢丝

该项目最引人注目的技术选择是no_std Rust。Rust的no_std模式意味着不能使用标准库(std),而只能使用core库——它提供基本类型、迭代器、智能指针,但没有堆分配、文件系统、网络等设施。通常情况下,编写一个依赖文件列表的工具,no_std几乎是“自缚双手”,因为文件操作需要系统调用。

开发者巧妙绕过了这一限制:通过FFI直接调用libc中的opendirreaddirclosedirstat等函数。也就是说,xls虽然是Rust代码,但文件系统操作完全交由C标准库代理,Rust层只负责数据解析和格式化输出。这样既保留了Rust的所有权模型和零成本抽象,又避免了引入std库中庞大的异步/IO运行时。整个项目仅使用了一个外部依赖:libc crate(提供Rust对libc的绑定)。

“选择no_std并非为了炫技,而是为了将二进制体积压缩到极致。Rust std的启动代码、动态内存分配器、panic处理等都会增加几百KB。如果连堆分配都不需要,那么panic_fmtalloc 都可以被剥离。”开发者在一篇技术笔记中解释。项目确实没有使用VecString,而是借用了heapless crate中的固定大小向量,所有输出缓冲区均在栈上预分配。

性能:小而快,但非全能

在性能方面,xls在目录条目数少于1000时几乎与GNU ls持平,甚至在某些场景下快5-10%,因为减少了动态分配和格式化开销。但在包含大量文件(>10000)的目录中,缺乏排序变得明显——GNU ls默认按字母排序,而xls直接按目录读取顺序输出,对于需要顺序查看的用户可能不够友好。另外,长格式下权限字符串的宽度固定为11字符(如drwxr-xr-x),不处理ACL和SELinux上下文,这也牺牲了部分兼容性。

社区反响:怀旧的极简主义与实用主义之争

在Hacker News的讨论中,赞弹参半。支持者怀念早期Unix工具的“单用途、小而美”哲学:“18KB的ls提醒我们,不是所有软件都需要成为瑞士军刀。容器镜像、嵌入式环境、甚至initramfs中,一个18KB的ls比几百KB的版本更有价值。”批评者则认为,在磁盘和内存不再是瓶颈的今天,牺牲功能换取体积并不明智:“我宁愿要一个能正确排序、处理宽字符、支持分页的ls,也不想为了省几百KB而忍受不便。”

该项目的衍生价值同样不可忽视:作为Rust no_std + FFI的示范案例,它为嵌入式Rust开发者提供了一个极好的参考——如何在不依赖std的情况下,通过libc桥接实现操作系统基本功能。开发者已计划将核心逻辑抽离成no_std兼容的crate,供其他极简工具(如catecho)复用。

前景:微工具生态的曙光?

无论最终是否能流行,xls都展示了Rust在“极小二进制”领域的巨大潜力。随着Serverless、Wasm、边缘计算等场景对体积的苛刻要求,类似18KB的lspsdf等工具或许会逐渐形成一个“微coreutils”子生态。它们不追求全功能,而是补足标准工具在体积敏感环境下的空缺。毕竟,当一个容器镜像只有5MB时,一个500KB的ls就显得格格不入了。

18KB,只是一个开始。如果你也对这种“手艺活”感兴趣,可以在GitHub上搜索“xls”(或相关项目名)。开发者已经贴心地提供了Makefile,一行make即可在你本机构建出一个不足巴掌大的ls——然后你会发现,原来删除冗余的感觉如此畅快。