nodejsのフォルダーの下にある* .html拡張子でファイルを検索します


92

nodejsを使用して、srcフォルダーとそのすべてのサブフォルダーにあるすべての* .htmlファイルを検索したいと思います。それを行うための最良の方法は何ですか?

var folder = '/project1/src';
var extension = 'html';
var cb = function(err, results) {
   // results is an array of the files with path relative to the folder
   console.log(results);

}
// This function is what I am looking for. It has to recursively traverse all sub folders. 
findFiles(folder, extension, cb);

多くの開発者は、優れたテスト済みのソリューションを用意する必要があると思います。自分で作成するよりも、それを使用する方がよいでしょう。


正規表現でファイルを検索する場合は、再帰的なファイル検索を同時に実行するfile-regexライブラリを使用します
AkashBabu20年

回答:


92

node.js、再帰的な単純な関数:

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

function fromDir(startPath,filter){

    //console.log('Starting from dir '+startPath+'/');

    if (!fs.existsSync(startPath)){
        console.log("no dir ",startPath);
        return;
    }

    var files=fs.readdirSync(startPath);
    for(var i=0;i<files.length;i++){
        var filename=path.join(startPath,files[i]);
        var stat = fs.lstatSync(filename);
        if (stat.isDirectory()){
            fromDir(filename,filter); //recurse
        }
        else if (filename.indexOf(filter)>=0) {
            console.log('-- found: ',filename);
        };
    };
};

fromDir('../LiteScript','.html');

ファンシーにしたい場合はRegExpを追加し、それを汎用にするためのコールバックを追加します。

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

function fromDir(startPath,filter,callback){

    //console.log('Starting from dir '+startPath+'/');

    if (!fs.existsSync(startPath)){
        console.log("no dir ",startPath);
        return;
    }

    var files=fs.readdirSync(startPath);
    for(var i=0;i<files.length;i++){
        var filename=path.join(startPath,files[i]);
        var stat = fs.lstatSync(filename);
        if (stat.isDirectory()){
            fromDir(filename,filter,callback); //recurse
        }
        else if (filter.test(filename)) callback(filename);
    };
};

fromDir('../LiteScript',/\.html$/,function(filename){
    console.log('-- found: ',filename);
});

デモコードをどうもありがとう!私はあなたのコードの上に何かを追加しました、そしてそれは素晴らしい働きをします!LiteScriptプロジェクトもチェックしましたが、すばらしいです。githubでスターを付けました!
Nicolas S.Xu 2014

また、拡張子なしのファイル名を見つけるための素晴らしい小さなスクリプト-私の場合、私はいくつかのJPEGファイルを持っていたし、別のディレクトリにある元のファイルがPNGまたはJPEGであれば見つけるために必要な、このことができます
リッキー・オーディンマシューズ

80

私はglobパッケージを使うのが好きです:

const glob = require('glob');

glob(__dirname + '/**/*.html', {}, (err, files)=>{
  console.log(files)
})

1
通常、単純なもののパッケージのファンではありませんが、globにノードjsの実装が組み込まれるのは時間の問題です。これは、ファイル選択の正規表現になるようなものです。
SephReed19年

27

なに、ちょっと待って!...わかりました、多分これは他の誰かにとってもより理にかなっています。

[ nodejs7気になります]

fs = import('fs');
let dirCont = fs.readdirSync( dir );
let files = dirCont.filter( function( elm ) {return elm.match(/.*\.(htm?html)/ig);});

正規表現で何でもして、デフォルトなどで関数に設定した引数にします。


2
これにより、ルートディレクトリ内の一致するファイルのみが取得されます。
dreamerkumar 2017年

6
編集しようとしましたが拒否されましたが、同意しません。これが私の提案です:stackoverflow.com/review/suggested-edits/19188733 wlは何でもとても理にかなっています。また、fsのインポートがありません。あなたが必要とする3行は、次のとおりです。1. const fs = require('fs');2. const dirCont = fs.readdirSync( dir );3.const files = dirCont.filter( ( elm ) => /.*\.(htm?html)/gi.test(elm) );
Avindra Goolcharan

申し訳ありませんが、wl.fsはインポートを介してfslibを保存した場所です。
マスタージェームス

ああインポートはおそらく今のところrequireを指す私自身のカスタム関数なので、requireまたはあなたがしなければならないことは何でも使用してください。
マスタージェームス

13

Lucioのコードに基づいて、モジュールを作成しました。その下に特定の拡張子を持つすべてのファイルが返されます。誰かがそれを必要とする場合に備えて、ここに投稿してください。

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


/**
 * Find all files recursively in specific folder with specific extension, e.g:
 * findFilesInDir('./project/src', '.html') ==> ['./project/src/a.html','./project/src/build/index.html']
 * @param  {String} startPath    Path relative to this file or other file which requires this files
 * @param  {String} filter       Extension name, e.g: '.html'
 * @return {Array}               Result files with path string in an array
 */
function findFilesInDir(startPath,filter){

    var results = [];

    if (!fs.existsSync(startPath)){
        console.log("no dir ",startPath);
        return;
    }

    var files=fs.readdirSync(startPath);
    for(var i=0;i<files.length;i++){
        var filename=path.join(startPath,files[i]);
        var stat = fs.lstatSync(filename);
        if (stat.isDirectory()){
            results = results.concat(findFilesInDir(filename,filter)); //recurse
        }
        else if (filename.indexOf(filter)>=0) {
            console.log('-- found: ',filename);
            results.push(filename);
        }
    }
    return results;
}

module.exports = findFilesInDir;

12

Filehoundを使用してこれを行うことができます。

例:/ tmp内のすべての.htmlファイルを検索します。

const Filehound = require('filehound');

Filehound.create()
  .ext('html')
  .paths("/tmp")
  .find((err, htmlFiles) => {
    if (err) return console.error("handle err", err);

    console.log(htmlFiles);
});

詳細(および例)については、ドキュメントを確認してくださいhttps//github.com/nspragg/filehound

免責事項:私は著者です。


8

私は上記の答えを見て、私のために働くこのバージョンを混ぜ合わせました:

function getFilesFromPath(path, extension) {
    let files = fs.readdirSync( path );
    return files.filter( file => file.match(new RegExp(`.*\.(${extension})`, 'ig')));
}

console.log(getFilesFromPath("./testdata", ".txt"));

このテストでは、パスのフォルダーにあるファイルからファイル名の配列が返されます./testdata。ノードバージョン8.11.3での作業。


1
私は正規表現の末尾に$を追加したい:.*\.(${extension})$
ユージン

3

これにはOSヘルプを使用できます。クロスプラットフォームソリューションは次のとおりです。

1.以下の関数はlsdir再帰的に検索し、検索しませんが、相対パスを持っています

var exec = require('child_process').exec;
function findFiles(folder,extension,cb){
    var command = "";
    if(/^win/.test(process.platform)){
        command = "dir /B "+folder+"\\*."+extension;
    }else{
        command = "ls -1 "+folder+"/*."+extension;
    }
    exec(command,function(err,stdout,stderr){
        if(err)
            return cb(err,null);
        //get rid of \r from windows
        stdout = stdout.replace(/\r/g,"");
        var files = stdout.split("\n");
        //remove last entry because it is empty
        files.splice(-1,1);
        cb(err,files);
    });
}

findFiles("folderName","html",function(err,files){
    console.log("files:",files);
})

2.次の関数はfindandを使用してdir再帰的に検索しますが、Windowsでは絶対パスがあります

var exec = require('child_process').exec;
function findFiles(folder,extension,cb){
    var command = "";
    if(/^win/.test(process.platform)){
        command = "dir /B /s "+folder+"\\*."+extension;
    }else{
        command = 'find '+folder+' -name "*.'+extension+'"'
    }
    exec(command,function(err,stdout,stderr){
        if(err)
            return cb(err,null);
        //get rid of \r from windows
        stdout = stdout.replace(/\r/g,"");
        var files = stdout.split("\n");
        //remove last entry because it is empty
        files.splice(-1,1);
        cb(err,files);
    });
}

findFiles("folder","html",function(err,files){
    console.log("files:",files);
})

1
私はrequire( 'child_process')。execに慣れていないので、この方法で実行できるとは思っていませんでしたが、見た目がとても良く、多くの考えを刺激します。ありがとうございました!
Nicolas S.Xu 2014

2
これは「nodejsを使用して」それを行う方法ではありません。これは、OSの使用、別のプロセスの起動などです。「。html」で終わるディレクトリがある場合も失敗します。例:files.html /
Lucio M. Tato

@ LucioM.Tato検索時にファイルタイプを指定できます。問題には多くの解決策があります。あなたの考えと一致しない場合、それは単にそれが間違っているという意味ではなく、ただ違うだけです。この回答は、使用されているスクリプト言語に関係なく、既存のソリューションを再利用できることを証明しています。
Emil Condrea 2014

もちろん、ディレクトリを繰り返し処理して特定の拡張子のファイルを見つけることは問題ありませんが、OSからすべての情報を受け取りたかったのは、彼がそれを実行できることを知っていたからです。:)
Emil Condrea 2014

@ EmilCondrea、IHMOこれはOPが尋ねたように「ノードを使用」していません。とにかく、それがあなたを悩ませているなら、私は反対票を削除します。
Lucio M. Tato 2014

3

次のコードは、。/内で再帰検索を実行し(適切に変更します)、. htmlで終わる絶対ファイル名の配列を返します。

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

var searchRecursive = function(dir, pattern) {
  // This is where we store pattern matches of all files inside the directory
  var results = [];

  // Read contents of directory
  fs.readdirSync(dir).forEach(function (dirInner) {
    // Obtain absolute path
    dirInner = path.resolve(dir, dirInner);

    // Get stats to determine if path is a directory or a file
    var stat = fs.statSync(dirInner);

    // If path is a directory, scan it and combine results
    if (stat.isDirectory()) {
      results = results.concat(searchRecursive(dirInner, pattern));
    }

    // If path is a file and ends with pattern then push it onto results
    if (stat.isFile() && dirInner.endsWith(pattern)) {
      results.push(dirInner);
    }
  });

  return results;
};

var files = searchRecursive('./', '.html'); // replace dir and pattern
                                                // as you seem fit

console.log(files);

2

file-regexを調べてください

let findFiles = require('file-regex')
let pattern = '\.js'

findFiles(__dirname, pattern, (err, files) => {  
   console.log(files);
})

上記のスニペットはjs、現在のディレクトリ内のすべてのファイルを出力します。


それは実際にそこにある最も簡単な解決策です。
kyeno

2

評判のためコメントを追加できませんが、次の点に注意してください。

fs.readdirまたはnode-globを使用して、500,000ファイルのフォルダー内のワイルドカードファイルセットを見つけるのに約2秒かかりました。DIRでexecを使用すると、約0.05秒(非再帰的)または約0.45秒(再帰的)かかりました。(1つのディレクトリで自分のパターンに一致する最大14個のファイルを探していました)。

これまでのところ、効率を求めて低レベルのOSワイルドカードを使用するnodejs実装を見つけることができませんでした。しかし、上記のDIR / lsベースのコードは、効率の点でWindowsでうまく機能します。ただし、Linuxの検索は、大きなディレクトリでは非常に遅くなる可能性があります


確かに興味深い。
philk

最新のnodejsfsモジュール(12.13 +?反復ディレクトリfns?)に新しい関数があることに注意してください。今のところ6.9.11で立ち往生しているので、まだ試していません。それらがこれに新しい便利な機能を提供するかどうかを確認するのは興味深いでしょう。今私の投稿について考えています。OSのキャッシュも考慮する必要があります。私の0.05は、何度も実行した後に測定された可能性があります。最初の「DIR」速度は何ですか?
サイモン

1

forループの代わりにマップを使用する私の2ペンス

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

var findFiles = function(folder, pattern = /.*/, callback) {
  var flist = [];

  fs.readdirSync(folder).map(function(e){ 
    var fname = path.join(folder, e);
    var fstat = fs.lstatSync(fname);
    if (fstat.isDirectory()) {
      // don't want to produce a new array with concat
      Array.prototype.push.apply(flist, findFiles(fname, pattern, callback)); 
    } else {
      if (pattern.test(fname)) {
        flist.push(fname);
        if (callback) {
          callback(fname);
        }
      }
    }
  });
  return flist;
};

// HTML files   
var html_files = findFiles(myPath, /\.html$/, function(o) { console.log('look what we have found : ' + o} );

// All files
var all_files = findFiles(myPath);

0

アプリケーションをブロックする可能性のあるsyncfsメソッドを使用していることに気づきました。これは、asyncqを使用したpromiseベースの非同期方法です。START= / myfolderFILTER = "。jpg"ノードmyfile.jsで実行できます。 myfile.jsというファイルに次のコードを入れたと仮定します。

Q = require("q")
async = require("async")
path = require("path")
fs = require("fs")

function findFiles(startPath, filter, files){
    var deferred;
    deferred = Q.defer(); //main deferred

    //read directory
    Q.nfcall(fs.readdir, startPath).then(function(list) {
        var ideferred = Q.defer(); //inner deferred for resolve of async each
        //async crawling through dir
        async.each(list, function(item, done) {

            //stat current item in dirlist
            return Q.nfcall(fs.stat, path.join(startPath, item))
                .then(function(stat) {
                    //check if item is a directory
                    if (stat.isDirectory()) {
                        //recursive!! find files in subdirectory
                        return findFiles(path.join(startPath, item), filter, files)
                            .catch(function(error){
                                console.log("could not read path: " + error.toString());
                            })
                            .finally(function() {
                                //resolve async job after promise of subprocess of finding files has been resolved
                                return done();
                             });
                    //check if item is a file, that matches the filter and add it to files array
                    } else if (item.indexOf(filter) >= 0) {
                        files.push(path.join(startPath, item));
                        return done();
                    //file is no directory and does not match the filefilter -> don't do anything
                    } else {
                        return done();
                    }
                })
                .catch(function(error){
                    ideferred.reject("Could not stat: " + error.toString());
                });
        }, function() {
            return ideferred.resolve(); //async each has finished, so resolve inner deferred
        });
        return ideferred.promise;
    }).then(function() {
        //here you could do anything with the files of this recursion step (otherwise you would only need ONE deferred)
        return deferred.resolve(files); //resolve main deferred
    }).catch(function(error) {
        deferred.reject("Could not read dir: " + error.toString());
        return
    });
    return deferred.promise;
}


findFiles(process.env.START, process.env.FILTER, [])
    .then(function(files){
        console.log(files);
    })
    .catch(function(error){
        console.log("Problem finding files: " + error);
})

4
コールバック地獄の素晴らしい例!:)
アフシンモアザミ2017

2
あなたは正しいです、再びこのようにしないでください:Dたぶん私は次の日に時間を見つけて、async / awaitでそれを解決して違いを示します。
Christoph Johannsdotter 2017

0

インストール

このパッケージをインストールすることができますwalk-syncによって

yarn add walk-sync

使用法

const walkSync = require("walk-sync");
const paths = walkSync("./project1/src", {globs: ["**/*.html"]});
console.log(paths);   //all html file path array

-2

古い投稿ですが、ES6はこのincludesメソッドで箱から出してこれを処理するようになりました。

let files = ['file.json', 'other.js'];

let jsonFiles = files.filter(file => file.includes('.json'));

console.log("Files: ", jsonFiles) ==> //file.json

私が使用file.readdirSyncしていて、拡張子でファイルを除外する簡単な方法が必要だったので、これに賛成するつもりです。これはこのスレッドの質問の一部に答えると思いますが、すべてではないかもしれません。まだ検討する価値があります。
justinpage
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.