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. 노호 기능 사용 ls및 dir및 재귀 적으로 검색하지 않습니다하지만 상대 경로가

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 메서드를 사용하고 있습니다. 여기에 async 및 q를 사용하는 약속 기반 비동기 방식 이 있습니다. 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.