nodejs의 폴더 아래에 * .html 확장자로 파일 찾기


89

src 폴더와 nodejs를 사용하여 모든 하위 폴더에서 모든 * .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 라이브러리 를 사용 하십시오 .
Akash Babu

답변:


90

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 년

또한 확장자없이 파일 이름을 찾기위한 좋은 작은 스크립트 - 내 경우에는 내가 다른 디렉토리에있는 원본 파일은 PNG 또는 JPEG 경우 찾을 수있는 몇 가지 사진과 필요가 있고,이 도움이
리키 오딘 매튜스

78

나는 glob 패키지를 사용하는 것을 좋아 합니다.

const glob = require('glob');

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

1
일반적으로 단순한 패키지의 팬은 아니지만 glob에 노드 js 구현이 내장되는 것은 시간 문제 일뿐입니다. 이것은 파일 선택의 정규 표현식이되는 것입니다.
Seph Reed 19

27

잠깐만 요?! ... 좋아, 아마도 이것은 다른 사람에게도 더 의미가 있습니다.

[ nodejs 7 마음에 들어요 ]

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

정규식을 사용하여 기본값 등으로 함수에서 설정 한 인수로 만드십시오.


2
이것은 루트 디렉토리에서 일치하는 파일 만 가져옵니다.
dreamerkumar

6
나는 편집을 시도했지만 거절 당했다. 내 제안은 다음과 같습니다. stackoverflow.com/review/suggested-edits/19188733 wl 은 너무 의미가 있습니다. 또한 fs에 대한 가져 오기가 누락되었습니다. 당신이 필요로하는 세 가지 라인은 다음과 같습니다 : 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는 가져 오기를 통해 fs lib를 저장 한 곳입니다.
마스터 제임스

오 가져 오기는 아마도 지금 당장 필요한 것을 가리키는 내 자신의 사용자 정의 함수이므로 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
RegExp 끝에 $를 추가합니다..*\.(${extension})$
Eugene

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. 벨로우즈 기능은 및를 사용 find하여 dir재귀 적으로 검색하지만 창에서는 절대 경로가 있습니다.

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-08-24

물론 디렉토리를 반복하고 특정 확장자를 가진 파일을 찾는 것이 잘못된 것은 아니지만, 그가 할 수 있다는 것을 알았 기 때문에 OS에서이 모든 정보를 받고 싶었습니다. :)
Emil Condrea 2014-08-24

@EmilCondrea, IHMO 이것은 OP가 요청한대로 "노드 사용"이 아닙니다. 어쨌든 당신을 괴롭 히면 반대표를 제거하겠습니다.
Lucio M. Tato 2014-08-24

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

평판 때문에 댓글을 추가 할 수 없지만 다음 사항에 유의하세요.

fs.readdir 또는 node-glob을 사용하여 500,000 개 파일 폴더에서 와일드 카드 파일 집합을 찾는 데 2 ​​초 정도 걸렸습니다. DIR과 함께 exec를 사용하면 ~ 0.05 초 (비 재귀) 또는 ~ 0.45 초 (재귀)가 소요되었습니다. (단일 디렉토리에서 내 패턴과 일치하는 ~ 14 개의 파일을 찾고있었습니다).

지금까지 효율성을 위해 낮은 수준의 OS 와일드 카드 검색을 사용하는 nodejs 구현을 찾지 못했습니다. 그러나 위의 DIR / ls 기반 코드는 효율성 측면에서 창에서 훌륭하게 작동합니다. 그러나 Linux find 는 큰 디렉토리의 경우 매우 느릴 수 있습니다 .


참으로 흥미 롭습니다.
philk

참고 최신 nodejs fs 모듈 (12.13+? 반복 디렉토리 fns?)에 새로운 기능이 있습니다. 나는 지금 6.9.11에 붙어 있기 때문에 아직 시도하지 않았습니다. 새로운 유용한 기능을 제공하는지 확인하는 것이 흥미로울 것입니다. 지금 내 게시물에 대해 생각하고 있습니다. OS 캐싱도 고려해야합니다. 내 0.05s는 여러 번 실행 한 후에 측정되었을 것입니다. 첫 번째 'DIR'속도가 무엇인지 궁금합니다.
Simon H

1

for-loop 대신 map을 사용하는 내 두 펜스

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);

1

파일 정규식 살펴보기

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

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

위의 스 니펫은 js현재 디렉토리의 모든 파일을 인쇄합니다 .


그것은 실제로 가장 쉬운 해결책입니다.
kyeno

0

방금 응용 프로그램을 차단할 수있는 sync fs 메서드를 사용하고 있습니다. 여기에 asyncq를 사용하는 약속 기반 비동기 방식 이 있습니다. START = / myfolder FILTER = ". jpg"node 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
콜백 지옥의 좋은 예! :)
Afshin Moazami

2
당신 말이 맞아요, 다시는 이런 식으로하지 않겠어요 : D 아마 다음날 시간을 찾아서 async / await로 해결해 차이를 보여줄 것입니다.
Christoph Johannsdotter

0

설치

이 패키지 워크 싱크 를 설치할 수 있습니다.

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.