如何使用Node.js在子文件夹中搜索文件文本内容
如何修改Node.js代码以支持子目录搜索指定扩展名文件中的目标文本?
我编写了一段Node.js代码,目的是查找指定扩展名文件中的目标文本。比如执行search.js txt alex时,需要在所有文件中查找字符串"alex"并返回完整文件名,但当前代码无法搜索子目录。请问如何修改以支持子目录搜索?
我的代码如下:
const fs = require('fs'); const path = require('path'); const dirPath = path.resolve(__dirname); let filesList; if (process.argv.length < 3) { console.log('USAGE: node search.js <extension> <search-text>'); process.exit(1); } const targetExt = process.argv[2]; const searchText = process.argv[3]; fs.readdir(dirPath, (err, files) => { if (err) { console.error('Error reading directory:', err); return; } filesList = files.filter(file => path.extname(file) === `.${targetExt}`); filesList.forEach(file => { const filePath = path.join(dirPath, file); fs.readFile(filePath, 'utf8', (err, content) => { if (err) { console.error('Error reading file:', err); return; } if (content.includes(searchText)) { console.log(filePath); } }); }); });
要让你的代码支持子目录搜索其实很简单,核心就是遍历目录时判断每个项是不是子目录,如果是就递归进去搜。下面给你两种实用的修改方案,适配不同的代码风格:
方案1:回调风格的递归遍历(和你原代码风格一致)
这种改动最小,直接在你现有代码基础上扩展:
const fs = require('fs'); const path = require('path'); const dirPath = path.resolve(__dirname); if (process.argv.length < 3) { console.log('USAGE: node search.js <extension> <search-text>'); process.exit(1); } const targetExt = process.argv[2]; const searchText = process.argv[3]; // 定义递归搜索函数,传入当前要遍历的目录 function searchDirectory(currentDir) { // 用withFileTypes选项直接获取文件类型,比单独调用fs.stat更高效 fs.readdir(currentDir, { withFileTypes: true }, (err, entries) => { if (err) { console.error(`读取目录出错 ${currentDir}:`, err); return; } entries.forEach(entry => { const fullPath = path.join(currentDir, entry.name); if (entry.isDirectory()) { // 碰到子目录,递归调用搜索函数 searchDirectory(fullPath); } else if (entry.isFile() && path.extname(entry.name) === `.${targetExt}`) { // 是符合扩展名的文件,就读取内容找目标文本 fs.readFile(fullPath, 'utf8', (err, content) => { if (err) { console.error(`读取文件出错 ${fullPath}:`, err); return; } if (content.includes(searchText)) { console.log(fullPath); } }); } }); }); } // 启动搜索 searchDirectory(dirPath);
关键改动点:
- 新增
searchDirectory递归函数,负责遍历当前目录并处理子目录 - 使用
fs.readdir的{ withFileTypes: true }参数,直接判断项是文件还是目录,省去额外的文件状态查询 - 保留你原有的文本匹配逻辑,只在符合扩展名的文件中执行搜索
方案2:现代Promise/async-await风格
如果你想让代码更简洁易读,可以用fs.promises模块配合async-await:
const fs = require('fs').promises; const path = require('path'); const dirPath = path.resolve(__dirname); if (process.argv.length < 3) { console.log('USAGE: node search.js <extension> <search-text>'); process.exit(1); } const targetExt = process.argv[2]; const searchText = process.argv[3]; async function searchDirectory(currentDir) { try { const entries = await fs.readdir(currentDir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(currentDir, entry.name); if (entry.isDirectory()) { await searchDirectory(fullPath); } else if (entry.isFile() && path.extname(entry.name) === `.${targetExt}`) { const content = await fs.readFile(fullPath, 'utf8'); if (content.includes(searchText)) { console.log(fullPath); } } } } catch (err) { console.error(`处理 ${currentDir} 时出错:`, err); } } // 启动搜索 searchDirectory(dirPath);
优势:
- 用async-await替代回调嵌套,代码结构更线性,调试起来更方便
- 统一用try-catch处理错误,不用在每个回调里单独写错误处理
额外小建议
- 如果要搜索的目录里有超大文件,建议用
readline模块逐行读取,避免一次性把整个文件加载到内存里 - 可以加个命令行参数让用户指定起始搜索目录,不用固定死
__dirname,工具会更灵活
内容的提问来源于stack exchange,提问作者Alex Bliznichenko
相关产品推荐
相关产品推荐

