You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:02:00