Javascript、Nodejs:在文件中搜索特定单词字符串

问题描述 投票:0回答:1

我正在尝试制作一个搜索所有文件的应用程序 当前目录/子目录下包含指定字符串。

据我了解,这意味着我需要创建一个读取流,循环它,将读取的数据加载到数组中,如果找到的单词给出 __filename、dirname 和 if !未找到消息。

不幸的是,我无法让它发挥作用...... 有什么线索吗?

var path = require('path'),
 fs=require('fs');

function fromDir(startPath,filter,ext){

    if (!fs.existsSync(startPath)){
        console.log("no dir ",startPath);
        return;
    };
    
    var files=fs.readdirSync(startPath);
    let found = files.find((file) => {
        let thisFilename = path.join(startPath, file);
        let stat = fs.lstatSync(thisFilename);
        var readStream = fs.createReadStream(fs);
        var readline = require('readline');
        if (stat.isDirectory()) {
            fromDir(thisFilename, filename,readline, ext);



        } else {
            if (path.extname(createReadStream) === ext && path.basename(thisFilename, ext) === filename) {
                return true;
        }
        }
        });

       

            console.log('-- your word has found on : ',filename,__dirname);
        }
     
    if (!found) { 
        console.log("Sorry, we didn't find your term");
    }

    }
    
    fromDir('./', process.argv[3], process.argv[2]);
   

javascript node.js arrays string file
1个回答
14
投票

因为问题中并未包含所有内容,所以我做了一个假设:

我们正在寻找完整的单词(如果不是这种情况,请将正则表达式替换为简单的

indexOf()
)。

现在,我将代码分成两个函数 - 使其更具可读性并且更容易递归地查找文件。

同步版本:

const path = require('path');
const fs = require('fs');

function searchFilesInDirectory(dir, filter, ext) {
    if (!fs.existsSync(dir)) {
        console.log(`Specified directory: ${dir} does not exist`);
        return;
    }

    const files = getFilesInDirectory(dir, ext);

    files.forEach(file => {
        const fileContent = fs.readFileSync(file);
        
        // We want full words, so we use full word boundary in regex.
        const regex = new RegExp('\\b' + filter + '\\b');
        if (regex.test(fileContent)) {
            console.log(`Your word was found in file: ${file}`);
        }
    });
}

// Using recursion, we find every file with the desired extention, even if its deeply nested in subfolders.
function getFilesInDirectory(dir, ext) {
    if (!fs.existsSync(dir)) {
        console.log(`Specified directory: ${dir} does not exist`);
        return;
    }

    let files = [];
    fs.readdirSync(dir).forEach(file => {
        const filePath = path.join(dir, file);
        const stat = fs.lstatSync(filePath);
        
        // If we hit a directory, apply our function to that dir. If we hit a file, add it to the array of files.
        if (stat.isDirectory()) {
            const nestedFiles = getFilesInDirectory(filePath, ext);
            files = files.concat(nestedFiles);
        } else {
            if (path.extname(file) === ext) {
                files.push(filePath);
            }
        }
    });

    return files;
}

异步版本 - 因为

async
很酷:

const path = require('path');
const fs = require('fs');
const util = require('util');

const fsReaddir = util.promisify(fs.readdir);
const fsReadFile = util.promisify(fs.readFile);
const fsLstat = util.promisify(fs.lstat);

async function searchFilesInDirectoryAsync(dir, filter, ext) {  
    const found = await getFilesInDirectoryAsync(dir, ext);

    for (file of found) {
        const fileContent = await fsReadFile(file);

        // We want full words, so we use full word boundary in regex.
        const regex = new RegExp('\\b' + filter + '\\b');
        if (regex.test(fileContent)) {
            console.log(`Your word was found in file: ${file}`);
        }
    };
}

// Using recursion, we find every file with the desired extention, even if its deeply nested in subfolders.
async function getFilesInDirectoryAsync(dir, ext) {
    let files = [];
    const filesFromDirectory = await fsReaddir(dir).catch(err => {
        throw new Error(err.message);
    });

    for (let file of filesFromDirectory) {
        const filePath = path.join(dir, file);
        const stat = await fsLstat(filePath);

        // If we hit a directory, apply our function to that dir. If we hit a file, add it to the array of files.
        if (stat.isDirectory()) {
            const nestedFiles = await getFilesInDirectoryAsync(filePath, ext);
            files = files.concat(nestedFiles);
        } else {
            if (path.extname(file) === ext) {
                files.push(filePath);
            }
        }
    };

    return files;
}

如果您尚未使用/理解 async/await,那么尽快采取并学习它是一个很好的步骤。相信我,你会喜欢不再看到那些丑陋的回调!

更新: 正如您在评论中指出的那样,您希望它在文件上运行

node
进程后执行该函数。您还想将函数参数作为
node
的参数传递。

为此,您需要在文件末尾添加:

searchFilesInDirectory(process.argv[2], process.argv[3], process.argv[4]);

这会提取我们的参数并将它们传递给函数。

这样,您就可以像这样调用我们的流程(示例参数):

node yourscriptname.js ./ james .txt

就我个人而言,如果我要写这个,我会利用异步代码的优点和 Node.js 的

async / await

作为一个旁注:

如果添加适当的格式,您可以轻松提高代码的可读性。不要误会我的意思,这并不可怕 - 但它可以改进:

  1. 在逗号后使用空格或换行符。
  2. 在等号运算符和算术运算符周围使用空格。

只要格式保持一致,一切看起来都会好得多。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.