` + `path.extname()` 实现按扩展名过滤的目录文件列表(filtered_ls 练习详解))
教程CLI【免费下载链接】learnyounodeLearn You The Node.js For Much Win! An intro to Node.js via a set of self-guided workshops.项目地址https://gitcode.com/gh_mirrors/le/learnyounode点击查看免费下载这篇技术指南以 learnyounode 课程中的 filtered_ls过滤目录列表练习为核心完整讲解如何编写一个读取指定目录、按文件扩展名过滤、并以一行一个文件的方式输出结果的 Node.js 命令行程序。读完本文你将掌握fs.readdir()异步回调的用法、process.argv的参数解析规则、path.extname()的扩展名提取技巧并了解该练习背后的自动化验证机制如何强制要求使用异步 I/O。所有结论均有本仓库的官方题目、参考答案与测试用例作为依据。练习目标从题目要求说起filtered_ls 是 learnyounode 入门序列中的第三道练习承接 baby_steps命令行参数与 my_first_async_io异步文件读取。本练习的完整题目原文见 exercises/filtered_ls/problem.md核心要求可拆解为四点新建文件程序必须保存在名为filtered-ls.js的文件中。两个命令行参数第一个参数是目标目录路径如/path/to/dir/第二个参数是用于过滤的文件扩展名如txt。过滤规则只输出文件名以.扩展名结尾的文件。特别注意——第二个参数传入时不带前导点号txt而非.txt程序内部需要自行拼接点号。输出与 I/O 要求每个匹配文件占一行打印到控制台并且必须使用异步 I/O禁止fs.readdirSync之类的同步方法。题目中还特别提醒了一个新手极易踩坑的点程序接收的参数不是process.argv数组的开头几个元素因为 Node 会把这个数组的前两个位置预留给系统信息第一个是 Node 可执行文件路径第二个是脚本文件路径。真正的用户参数从process.argv[2]开始。从题目信息problem.md 的 HINTS 小节可知这道练习希望用到 Node 内置模块fs负责读取目录和path负责提取扩展名对应仓库内还内置了官方文档镜像/docs-nodejs/fs.html 与 docs-nodejs/path.html可随时查阅。核心 API 讲解fs.readdir()与path.extname()fs.readdir(pathname, callback)异步读取目录fs.readdir()是 fs 模块中用于列出目录内容的异步方法其第一个参数是目录路径第二个参数是回调函数回调签名固定为function callback (err, list) { /* ... */ }其中list是一个由文件名组成的字符串数组且数组内的名字只包含文件名本身不含完整路径因此后续无法直接对它做路径拼接需要配合path模块处理。如果读取失败err会携带错误信息成功时err为null。fs.readdir()的完整 API 文档包括fs.readdirSync、fs.promises.readdir等变体收录在本仓库的 docs-nodejs/fs.html 中可以作为离线查阅的权威参考资料。path.extname(file)提取文件扩展名path.extname()接收一个文件名字符串返回其扩展名部分返回结果自带前导点号。例如const path require(path) path.extname(learnyounode.txt) // .txt path.extname(README.md) // .md path.extname(LICENCE.md) // .md path.extname(learnyounode) // 无扩展名返回空字符串这正好与题目“第二个参数不带点号”的规则形成互补程序中把用户传入的txt拼接成.txt再与path.extname()的结果做全等比较即可准确过滤。path模块的完整文档同样可在仓库中查阅docs-nodejs/path.html。参考答案一份可直接运行的最小实现仓库在 exercises/filtered_ls/solution/solution.js 中给出了官方参考实现代码非常精简完整如下use strict const fs require(fs) const path require(path) const folder process.argv[2] const ext . process.argv[3] fs.readdir(folder, function (err, files) { if (err) return console.error(err) files.forEach(function (file) { if (path.extname(file) ext) { console.log(file) } }) })这段代码的运行逻辑可以拆解为四个步骤每一步都对应上文的核心 API取参process.argv[2]为目录路径process.argv[3]为扩展名并提前拼接点号得到ext . process.argv[3]。异步读取调用fs.readdir(folder, callback)将目录中所有文件名一次性放入回调的list此处命名files参数。错误处理回调内先判断err若出错立即console.error(err)并return避免在空数组上继续操作。过滤输出用Array.prototype.forEach遍历files凡path.extname(file) ext的文件逐一console.log(file)——每行一个文件正好满足“一行一个”的输出要求。与官方解在写法上略有差异但同样正确的风格也很常见先filter()再forEach()例如测试用例 test/filtered_ls/valid_01.js 正是这种写法fs.readdir(process.argv[2], function (err, list) { if (err) { console.log(err) } list.filter(function (file) { return path.extname(file) . process.argv[3] }).forEach(function (file) { console.log(file) }) })两种实现殊途同归读者可按个人偏好选择。验证机制解剖自动化检查如何强制异步 I/O学习本练习理解其验证逻辑比通过练习本身更有价值。该练习的验证器在 exercises/filtered_ls/exercise.js 中其验证策略分为三个阶段1. 构造真实的测试目录addSetup阶段会在系统临时目录os.tmpdir()下创建一个以进程 PID 命名的目录_learnyounode_pid然后依据 exercises/filtered_ls/file-list.json 中的文件清单逐个写入内容为nothing to see here的测试文件。该清单精心构造了多种边界情况一共 15 个文件其中包括[ learnyounode.dat, learnyounode.txt, learnyounode.sql, api.html, README.md, CHANGELOG.md, LICENCE.md, md, data.json, data.dat, data.dat, words.dat, w00t.dat, w00t.txt, wrrrrongdat, dat ]从源码结构看这个清单设计的意图非常明确既有.txt、.md、.dat等多种常规扩展名也有md、dat、wrrrrongdat这类不带点号、恰好与扩展名同名的干扰项——如果程序只用endsWith()而不用path.extname()就很容易被这些干扰项“误伤”。这从侧面印证了path.extname()才是正确的过滤方式。验证阶段传入的参数固定为md即过滤出所有.md文件期望输出仅为api.html、README.md、CHANGELOG.md、LICENCE.md之外……实际上过滤md扩展名时README.md、CHANGELOG.md、LICENCE.md命中。2. 包装 fs 模块以记录调用验证器通过workshopper-wrappedexec包装子进程并加载 exercises/my_first_io/wrap.js 作为运行时探针该模块会遍历fs对象的所有方法逐一替换为记录调用的代理函数通过调用栈判断这些 fs 调用是否来自用户提交的主程序并记入ctx.fsCalls。这样一来无论用户程序内部调用的是同步还是异步方法都会被如实登记。3. 判定规则addVerifyProcessor阶段遍历exercise.wrapData.fsCalls记录的所有被调用过的 fs 方法名凡是方法名以Sync结尾如fs.readdirSync判定为违规使用同步 I/O输出失败信息其余方法视为异步调用输出通过信息如果用户程序压根没调用任何 fs 方法既无同步也无异步同样判定失败这是为了防止用child_process.exec(ls ...)之类的手段绕过练习核心目的。最终callback(null, usedAsync !usedSync)即只有至少使用了一次异步 fs 调用、且完全没碰同步调用时才通过验证。对应地测试目录中的反例也分两类/test/filtered_ls/invalid_01.js 使用fs.readdirSync同步 I/O/test/filtered_ls/invalid_02.js 使用child_process.exec(ls -1 ...)绕过 fs两者都会被验证器拒收。运行与提交验证编写好filtered-ls.js后可以在本仓库根目录下先手动运行一遍确认输出符合预期# 手动运行第一个参数为目录第二个参数为扩展名 node exercises/filtered_ls/solution/solution.js /path/to/dir txt # 使用 learnyounode 内置的本地文档进行离线自学 # fs 模块文档docs-nodejs/fs.html # path 模块文档docs-nodejs/path.html然后通过 learnyounode 的验证命令检查程序是否正确对应 problem.md 末尾的说明learnyounode verify filtered-ls.js验证通过后本课程还会在下一题 make_it_modular模块化改造 中要求把同样的过滤逻辑抽成独立模块、通过回调返回结果——届时fs.readdir的异步回调模式会继续复用配套的模块化验证器也位于 exercises/make_it_modular/verify.js。因此扎实吃透本练习的异步思维是后续进阶的基石。常见错误自查清单结合验证器规则与官方反例提交前可对照以下清单自查检查项正确做法常见错误参数下标从process.argv[2]开始取从process.argv[0]开始误取到系统信息扩展名处理用path.extname()或自行拼接.前缀直接用endsWith(ext)被md、dat等干扰项误命中I/O 方式fs.readdir()异步使用fs.readdirSync()或child_process.exec(ls)绕过错误处理回调内先判err忽略err导致后续空数组操作抛错输出格式每个文件单独一行console.log(file)用数组join( )打在同一行小结filtered_ls 这道练习虽小却浓缩了 Node.js 入门阶段最核心的三个基本功process.argv命令行参数解析、fs.readdir()的异步回调模式、以及path.extname()对文件名结构的标准化处理。通过本文对官方参考答案solution.js与验证器源码exercise.js的逐层剖析你不仅知道“怎么写能通过”更理解了“验证器为什么能拦截同步写法”——这种对运行机制本身的理解比单纯通关更有长期价值。赞分享教程CLI【免费下载链接】learnyounodeLearn You The Node.js For Much Win! An intro to Node.js via a set of self-guided workshops.项目地址https://gitcode.com/gh_mirrors/le/learnyounode点击查看免费下载相关推荐learnyounode 实战使用 fs.readdir 与 path.extname 实现按扩展名过滤的异步目录列表filtered_ls 练习详解learnyounode 实战使用 fs.readdir 与 path.extname 实现按扩展名过滤的异步目录列表filtered_ls 练习详解 本教程CLIlearnyounode 实战用 fs.readdir 与 path.extname 实现按扩展名过滤的目录列表FILTERED LS 详解learnyounode 实战用 fs.readdir 与 path.extname 实现按扩展名过滤的目录列表FILTERED LS 详解 导读 本文以教程CLIinfluence-release部署指南在真实项目中应用影响函数分析influence release部署指南在真实项目中应用影响函数分析 influence release是一个基于影响函数Influence Functi教程CLI上一篇7大核心组件构建实时数据处理管道从数据风暴到决策洞察的全链路实践下一篇基于 agno 环境框架对比推理强度策略Policy Settings 指南与测试实证创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考