C++17 std::filesystem实战:路径处理、遍历与清理工具
在C里写文件系统操作以前是件让人有点拧巴的事。你需要在不同操作系统之间维护完全不同的代码路径要么就一直带着一个笨重的三方依赖过活。C17引入的std::filesystem算是标准库终于正面回应了这个老问题。这篇文章不是照着文档念API我按自己的使用经验把路径处理、目录遍历、错误处理这些最常踩坑的点拆开讲最后给出一个按修改时间清理旧文件的完整工具实现。无论你是刚开始用C17还是已经在生产环境里碰过std::filesystem里面关于平台差异和错误恢复的细节应该都有参考价值。1. 为什么文件系统操作在C里一直是块硬骨头1.1 没进入标准库之前的日子在C17之前操作文件系统这件事的尴尬在于标准库只提供基本的文本流和二进制流读写但判断一个路径是否存在递归遍历目录获取文件修改时间这类高频操作全部要自己动手。跨平台这个词说起来轻巧但实际处理的时候全是细节。Windows路径分隔符是反斜杠POSIX路径是正斜杠Windows路径有盘符概念POSIX路径没有文件权限模型Windows和Linux完全两套符号链接在各种平台上的语义也有细微差别。想在项目里同时支持Windows和Linux通常的做法是写一堆封装类再用条件编译切出不同平台的实现。我接手过一个老项目文件操作部分是用宏和预处理指令堆出来的代码长这样#ifdef _WIN32 std::string dir C:\\data\\temp\\; const char sep \\; #else std::string dir /data/temp/; const char sep /; #endif std::string path dir file sep name.txt;用字符串拼接路径意味着每个需要拼接的地方都要记得维护分隔符变量。更麻烦的是递归遍历——你得分别调用Windows的文件查找API和POSIX的opendir/stat然后把两套结果抽象成同一个接口。工作量大还容易被忽略边界。比如Windows API的路径最大长度默认是260个字符如果没提前处理长路径程序会莫名其妙地失败而Linux几乎没有这个限制。这类平台差异在项目初期根本测不出来都是到了客户现场才爆雷。1.2 标准库的取舍与设计思路std::filesystem最早脱胎于Boost.Filesystem这个库在Boost里打磨了很多年C17正式进入标准库之后大部分接口保持了兼容。设计上最重要的一点是所有操作都围绕std::filesystem::path展开而不是像以前那样直接操作字符串。path类自带平台相关的编码和分隔符处理逻辑。你在Windows上写入a/b/c内部会按当地约定理解路径在Linux上写入a\\b\\c也会按POSIX的规则解析而不是把你的路径当成一串无意义的字符。这类处理对应了标准库的设计取舍跨平台代码看起来统一底层实现各自管理细节。在用std::filesystem之前我还是建议你先明确一点它覆盖的是文件系统的常规操作不是高性能文件扫描方案。目录遍历单次执行的开销不算小如果你要每秒扫描几十万个文件standard库这个层次满足不了你的极致性能需求那已经超出了这个库的定位。大部分业务场景比如批量改名、清理日志、配置文件查找它的性能和易用性足够。2. 路径处理字符串是表象path类才是本体2.1 三种拼接方式两种容易踩坑path类最核心的价值是把路径当作结构化对象而不是一串字符。它支持/运算符直接拼接路径也提供append和concat两个看起来像、行为却完全不同的成员函数。namespace fs std::filesystem; fs::path base /home/project; fs::path p1 base / src / main.cpp; // 推荐语义清晰 fs::path p2 base; p2.append(include/version.h); // 等价于 base / include/version.h fs::path p3 base; p3.concat(README.md); // 直接拼字符串结果是 /home/projectREADME.mdappend和运算符/都会在两个路径之间补分隔符而concat只是字符串的相加不会插入分隔符。实际开发中简洁地用/通常足够但有一种情况需要注意如果你从配置文件或用户输入中读取了一个子路径再拼接进基础目录不要用concat否则就会和上面一样把两段路径连成一段混乱的字符串。还有一个常被忽略的点operator/它本身会修改左操作数其实和append是一个语义但有些工程师只用/运算符的返回值形式。这个没有对错习惯上我更推荐返回值形式因为这样更容易写在一行链式拼接里fs::path config fs::path(/etc) / myapp / config.json;2.2 相对路径和绝对路径的正确转换判断一个路径是不是绝对路径可以用is_absolute()或者is_relative()。这两个方法看起来简单但不同操作系统会产生奇特的结果。比如Windows上这个路径fs::path p C:Users/root/data; std::cout p.is_absolute() std::endl; // Windows上可能是 false因为带盘符但没有前导反斜杠的路径在Windows语义里被称为盘符相对路径表示从当前工作目录的指定盘符来解析。这是Windows特有的概念。如果你的程序要输出一个绝对路径方便用户拷贝不能只看is_absolute()的返回值就认为它真是绝对的还需要结合文件系统状态判断。把相对路径转绝对路径标准库给了三个函数很多人分不清函数行为是否要求路径存在absolute(p)纯粹把当前工作目录和p拼接成绝对路径否weakly_canonical(p)规范化路径解析.和..不解析符号链接否canonical(p)规范化路径并解析所有符号链接得到绝对路径是路径必须存在实战经验是用户提交一个存在的文件路径时用canonical最稳妥能得到没有符号链接干扰的真实路径。如果路径可能不存在比如用户复制一个尚待创建的新文件路径只能用weakly_canonical或absolute否则一调用就会抛异常。要不要处理异常正是下一章节要聊的错误模式。2.3 组件访问文件名和扩展名从来没有你想的那么简单path类提供了parent_path、filename、stem、extension这些组件访问成员。它们面向的是路径的结构化解析而不是简单的字符串截取。fs::path file /usr/local/lib/libfoo.so.1.2; std::cout file.filename() std::endl; // libfoo.so.1.2 std::cout file.stem() std::endl; // libfoo std::cout file.extension() std::endl; // .2注意extension()返回的是最后一个点号之后的后缀。对于libfoo.so.1.2这种带多个点号的Linux库文件名你得到的扩展名是.2而不是.so。这不是bug标准就是这样定义的。如果你需要识别.tar.gz这类复合扩展名或者想提取Linux.so的版本号靠extension()一次调用做不到还得自己处理stem()再解析一次。常见需求是判断一个路径有没有特定扩展名。可以直接这么写if (p.extension() .cpp || p.extension() .cc) { // 是C源码 }也要知道path(a.txt).has_extension()在文件名以点号开头时返回false比如.gitignore没有扩展名.bashrc也没有。这个反直觉的行为在写文件分类程序时经常坑到人。3. 目录遍历迭代器、选项和错误恢复3.1 层次选择普通遍历 vs 递归遍历std::filesystem给了两个迭代器directory_iterator和recursive_directory_iterator。前者只遍历当前目录一层后者默认会深入所有子目录。选择本身不难关键要理解递归遍历的默认行为。recursive_directory_iterator在构造时会把入口目录入栈每次operator都会往栈里压入新发现的子目录。这意味着它无处不在的内存代价和执行顺序并不保证是按深度优先的标准顺序如果你在遍历过程中删除或移动了当前目录迭代器的行为可能就不可预期甚至直接抛异常。有人说遍历时千万不要删除文件这在directory_iterator层面没有那么恐怖但要注意清空一个目录的官方做法还是先递归遍历文件、逐个删除最后删除空目录本身。我试过在遍历过程中直接fs::remove_all整个根目录程序确实会抛filesystem_error然后迭代器失效。所以如果业务逻辑涉及边遍历边删除建议先把需要删除的文件路径收集到一个std::vector里遍历结束后统一删除。后面第5章的清理工具就是这么设计的。3.2 directory_options两个选项的实际价值recursive_directory_iterator构造时可以带一个directory_options我实际使用下来最有用的是skip_permission_denied。默认情况下遇到没有读权限的子目录迭代器会抛异常。对一个大目录做全盘扫描比如扫描整个用户目录一定会碰到权限不足的文件夹Windows有System Volume InformationLinux有/proc下的各类隐藏目录程序一旦抛异常整个扫描就中断了。std::error_code ec; fs::recursive_directory_iterator iter( root, fs::directory_options::skip_permission_denied, ec );这个选项的含义是跳过无权访问的子目录而不是终止遍历。它在尽量多扫描的场景下非常有用。还有一个follow_directory_symlink选项默认不跟随目录符号链接。原因很直接如果不加控制符号链接可能指向父目录形成无限循环。默认关闭从安全角度来说是对的如果你确实需要跟随又担心环的问题得自己维护一个已访问的目录集合或者限制递归深度。3.3 遍历中错误码的正确收集方式迭代器支持两种错误处理方式。一种是传统异常模式遇到filesystem_error就抛出你可以在外层写try/catch一把抓。另一种是更精细的std::error_code模式把错误码传入构造每次递增迭代器时也传入一个error_code。我见过不少项目只有外层套一个大try/catch一旦一个文件抛出权限异常整个扫描中断。如果换成错误码模式就可以记录下具体哪些路径出错而不是整个任务失败void scan_dir(const fs::path dir) { std::error_code ec; auto iter fs::directory_iterator(dir, ec); if (ec) { std::cerr 构造迭代器失败: ec.message() \n; return; } while (iter ! fs::directory_iterator()) { const auto entry *iter; if (fs::is_regular_file(entry.status(ec))) { std::cout entry.path().string() \n; } if (ec) { std::cerr 处理 entry.path() 时出错: ec.message() \n; ec.clear(); } iter.increment(ec); if (ec) { std::cerr 迭代异常路径: entry.path() \n; ec.clear(); } } }这里有个细节entry.status(ec)和entry.symlink_status()不同。前者会跟随符号链接返回目标文件状态后者返回符号链接本身的状态。判断一个目录项是不是符号链接一定要用symlink_status()。4. 文件状态、权限和时间戳容易被忽略的边界4.1 异常模式与error_code模式的协同使用std::filesystem几乎所有带返回值的函数都提供两个重载版本一个抛出filesystem_error异常一个接收std::error_code返回结果。两条路都能完成同样的功能关键在于怎么选择。我经验是对确定会失败的常规操作用异常模式会让代码更简单。比如读取一个肯定存在的配置文件直接fs::file_size()然后try失败就统一处理逻辑很清晰。但对批量处理大量文件、其中个别失败应该继续忽略的场景用error_code模式更合适。一个重要的区别是异常模式的what()字符串里包含发生错误的路径和原因这对日志排查非常友好而error_code模式只有错误码和message()往往看不到具体路径。我的实践是日志里把正在操作的文件路径自己加进去std::error_code ec; auto size fs::file_size(some/path, ec); if (ec) { log_error(获取文件大小失败, some/path, ec); return; }4.2 文件类型和权限位判断file_type枚举定义了文件类型not_found、regular、directory、symlink、fifo、socket等。标准库提供了is_regular_file、is_directory、is_symlink这类快捷函数它们内部直接基于file_status判断。判断方式有讲究。直接传路径给fs::is_regular_file(路径)会额外做一次系统调用获取状态。如果你在目录遍历中逐个判断每个entry完全可以复用entry.status()得到的状态避免重复调用for (const auto entry : fs::directory_iterator(dir)) { std::error_code ec; auto st entry.status(ec); if (ec) { continue; } if (st.type() fs::file_type::regular) { // 普通文件 } else if (st.type() fs::file_type::directory) { // 子目录 } }权限位操作在POSIX和Windows语义不互通但可以从status().permissions()读取。用perms按位与判断可读可写auto st fs::status(path, ec); if (!ec) { if ((st.permissions() fs::perms::owner_read) ! fs::perms::none) { // 对所有者可读 } if ((st.permissions() fs::perms::owner_write) ! fs::perms::none) { // 对所有者可写 } }这里特别提醒一下permissions()返回的是完整权限位你如果想判断没有写权限一定要和具体权限位做按位与后判断而不是直接比较相等因为目录和普通文件的默认权限位可能完全不同。4.3 时间戳读取与修改的常见误区last_write_time()返回一个std::filesystem::file_time_type它是基于系统时钟的时长类型。C20之前标准库没有直接输出人类可读格式的接口要转成time_t再格式化。auto mtime fs::last_write_time(path, ec); if (!ec) { auto sctp std::chrono::time_point_caststd::chrono::system_clock::duration(mtime); std::time_t t std::chrono::system_clock::to_time_t(sctp); std::cout std::ctime(t); }注意file_time_type和system_clock::time_point的实际时钟类型不一定一致标准库实现可能不同直接相减或比较在某些编译器上会报类型不匹配。用time_point_cast转换是比较稳妥的写法。修改文件修改时间用fs::last_write_time(path, new_time)在Windows上会精确到100纳秒但精度不等于设置一定能成功——如果你设过去的某个时间点早于文件系统支持的最早时间或者目标文件系统是只读挂载调用就会带error_code失败。在文件同步、增量备份这类工具中这些失败必须记录下来否则会误认为备份成功。5. 组合实战做一个按修改时间清理旧文件的工具5.1 基础循环与关键设计现在把前面聊的知识凑起来做一个实用的小工具扫描指定目录下所有普通文件删除超过N天没有修改的。这个工具很常见——清理临时目录、清理构建缓存、清理日志归档都是它的用武之地。设计上我做三个决定第一全部用error_code模式单文件失败不影响整体扫描 第二边遍历边收集需要删除的文件列表遍历结束后统一删除避免遍历中操作文件系统导致迭代器失效 第三删除时用fs::remove而不是fs::remove_all因为遍历时已经通过entry.is_regular_file()从类型上过滤掉了目录。主体代码#include filesystem #include iostream #include vector #include chrono namespace fs std::filesystem; int clean_old_files(const fs::path target, std::chrono::days max_age) { std::error_code ec; const auto now fs::file_time_type::clock::now(); std::vectorfs::path to_delete; to_delete.reserve(128); fs::recursive_directory_iterator iter( target, fs::directory_options::skip_permission_denied, ec ); if (ec) { std::cerr 无法打开目录: target - ec.message() \n; return 1; } while (iter ! fs::recursive_directory_iterator()) { const auto entry *iter; auto st entry.status(ec); if (ec) { ec.clear(); iter.increment(ec); continue; } if (!fs::is_regular_file(st)) { iter.increment(ec); continue; } auto mtime entry.last_write_time(ec); if (ec) { ec.clear(); iter.increment(ec); continue; } if (now - mtime max_age) { to_delete.push_back(entry.path()); } iter.increment(ec); if (ec) { std::cerr 迭代出错: entry.path() - ec.message() \n; ec.clear(); } } int deleted 0; for (const auto p : to_delete) { fs::remove(p, ec); if (ec) { std::cerr 删除失败: p - ec.message() \n; ec.clear(); } else { deleted; std::cout 已删除 p \n; } } return deleted; }这个工具的关键边界问题就是错误恢复。skip_permission_denied保证了遇到无权限子目录不会中断。边遍历边删的问题通过两阶段设计解决。剩余的空目录不清理是因为需求里只说清普通文件如果是清理整个目录树需要在文件删除后反向遍历目录把空目录也删掉。5.2 扩展一下按大小分组做重复文件初步检测同样的遍历框架改个小需求就能变成重复文件检测的雏形。先按文件大小分组同一组内再做内容比对避免对每个文件都做全文哈希。std::mapstd::uintmax_t, std::vectorfs::path by_size; for (const auto entry : fs::recursive_directory_iterator(target, fs::directory_options::skip_permission_denied, ec)) { auto st entry.status(ec); if (ec || !fs::is_regular_file(st)) { ec.clear(); continue; } by_size[fs::file_size(entry.path(), ec)].push_back(entry.path()); } for (const auto [size, paths] : by_size) { if (paths.size() 1 size 0) { std::cout 大小 size : ; for (const auto p : paths) { std::cout p ; } std::cout \n; } }大小相同只是候选真正确认还要逐块哈希比对。这个例子想说明的是std::filesystem的组合能力很强遍历、状态、大小查询粘在一起就是一个基础工具剩下的业务逻辑才是你自己的核心竞争力。5.3 性能方面的一些实话std::filesystem遍历文件的速度受操作系统和文件系统类型影响很大。单个目录几万文件遍历加上取状态大致是毫秒到几十毫秒的级别。它的性能当然比不上一套专用的扫描引擎但大部分管理类任务都够用。真要优化有一个方向值得注意减少status的系统调用次数。可以调查一下你的场景能否只依赖entry提供的信息或者用read_directory这类批量接口减少用户态和内核态的切换。还可以把last_write_time的判断放进一个哈希表中缓存避免重复调用。6. 从std::filesystem向外走一步std::filesystem不是终点它只是把大多数日常任务从不能做变成了能用。C20之后std::format风格的路径输出、std::janitor这类新提案也在逐步解决文件系统库剩下的细节问题。但对我来说在把权限、错误码、符号链接这些概念梳理清楚之前谈更多新特性意义不大——基础不牢后面写工具迟早要回来补课。我在实际项目里最深的感触是std::filesystem代码看着简单但它把平台差异从你的代码里抽走了同时要求你对文件系统的抽象有更精细的认识。符号链接和真实文件的区别、权限位在不同平台的语义差异、遍历时的错误恢复这些概念和API本身同等重要。写这篇东西算是把这几年反复踩过的坑集中记下来下次再碰到清理旧文件查找大文件对比目录结构这类需求我基本上会直接打开这套现成的心得去套。

相关新闻

区分agent中长期记忆和偏好记忆

区分agent中长期记忆和偏好记忆

一句话区分&#xff1a;长期记忆记"发生过的事"&#xff0c;偏好记忆记"这个人是什么样的人"。1. 数据结构完全不同长期记忆 LongTermMemory&#xff1a;一个会遗忘、会合并的列表List<MemoryItem> items // 每条 {id, content, importance, embedd…

2026/10/18 5:54:46 阅读更多 →
Linux iSCSI Target实战:用targetcli配置块级网络存储

Linux iSCSI Target实战:用targetcli配置块级网络存储

1. 为什么今天还要学iSCSI&#xff1f;——当本地磁盘开始“远程打工”很多人看到“iSCSI”三个字母&#xff0c;第一反应是&#xff1a;“这玩意儿不是2005年就该淘汰了吗&#xff1f;现在不都用NVMe over Fabrics、Ceph或者云盘API了&#xff1f;”我第一次在某高校实验室接手…

2026/10/18 5:53:46 阅读更多 →
微信小程序传染病防控系统实战:源码拆解与Docker一键部署

微信小程序传染病防控系统实战:源码拆解与Docker一键部署

做这类“传染病防控”小程序最怕什么&#xff1f;不是功能写不出来&#xff0c;而是做出来之后没人敢用、没人认账。疫情信息涉及健康隐私&#xff0c;用错一个字段、漏传一次数据&#xff0c;都可能引发合规和信任问题。我自己前后做过几套类似的课题和项目&#xff0c;从“单…

2026/10/18 5:53:45 阅读更多 →

最新新闻

MATLAB实现物元分析法:工程级可拓评价系统

MATLAB实现物元分析法:工程级可拓评价系统

简介&#xff1a;本资源是一套基于MATLAB实现的物元分析法完整计算工具包&#xff0c;面向高校科研人员、系统工程与管理科学方向的研究生及可拓学初学者&#xff0c;用于解决多指标综合评价中的定量化建模难题。资源包含5个核心文件&#xff1a;4个Excel数据表&#xff08;分别…

2026/10/18 6:59:58 阅读更多 →
Python + Vue校园社交平台开发实战:Flask/Django选型与前后端分离架构详解

Python + Vue校园社交平台开发实战:Flask/Django选型与前后端分离架构详解

校园社交平台这个方向&#xff0c;我在实际带项目的过程中见过太多次了。每次有同学拿着类似的题目来找我&#xff0c;我都先问一句&#xff1a;你确定要做社交&#xff1f;不是做一个课程设计交差就行&#xff1f;这个问题的答案&#xff0c;直接决定了项目后面是走Flask轻量路…

2026/10/18 6:59:58 阅读更多 →
技术标题解析方法论:如何科学验证模糊缩写rea

技术标题解析方法论:如何科学验证模糊缩写rea

项目标题为“rea”&#xff0c;但提供的输入内容中未给出任何有效上下文&#xff1a;无项目正文、无关键词列表、无摘要描述&#xff0c;相关热搜词与网络热词栏为空&#xff0c;搜索内容部分亦为空白。这意味着——该标题当前不具备可拆解的信息基础。作为一名从业十余年、经手…

2026/10/18 6:59:58 阅读更多 →
银行股实操指南:底仓+股息+波段,建立稳健投资框架

银行股实操指南:底仓+股息+波段,建立稳健投资框架

1. 项目概述“股市赚钱学概论&#xff1a;答疑&#xff1a;如何实操大银行”这个标题&#xff0c;乍看像是一个玩笑——把“赚钱学”和“大银行”放在一起&#xff0c;既不像正规金融教材&#xff0c;也不像常见的“龙头战法”“打板秘籍”。但恰恰是这个组合&#xff0c;暴露了…

2026/10/18 6:59:58 阅读更多 →
SVM缺页处理机制全解析:从NPT到KVM的性能优化实践

SVM缺页处理机制全解析:从NPT到KVM的性能优化实践

SVM&#xff08;AMD Secure Virtual Machine&#xff09;是AMD处理器上的虚拟化扩展&#xff0c;而缺页处理机制是虚拟化内存管理里最容易被低估、但实际影响极大的一个环节。很多做虚拟化平台的人把注意力放在调度、中断、IO虚拟化上&#xff0c;等到业务出现诡异的卡顿或者大…

2026/10/18 6:59:58 阅读更多 →
OpenClaw(Clawdbot)本地部署指南:从零构建24小时AI助理与自动化工作流

OpenClaw(Clawdbot)本地部署指南:从零构建24小时AI助理与自动化工作流

1. 从“一周只工作2天”说起&#xff1a;我为什么认真琢磨起了AI助理先别急着把“未来一周只工作2天”当成一个段子。作为一个常年被日报、周报、数据汇总、消息回复淹没的从业者&#xff0c;我第一次听到这个观点时也觉得是专家的嘴骗人的鬼。但当我花了几个周末&#xff0c;把…

2026/10/18 6:58:58 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →