web-dev-qa-db-ja.com

Node.jsのディレクトリにあるすべてのファイルの名前のリストをどのようにして取得しますか?

Node.jsを使ってディレクトリに存在するすべてのファイルの名前のリストを取得しようとしています。出力がファイル名の配列であることを望みます。これどうやってするの?

770
resopollution

fs.readdir または fs.readdirSync メソッドを使用できます。

fs.readdir

const testFolder = './tests/';
const fs = require('fs');

fs.readdir(testFolder, (err, files) => {
  files.forEach(file => {
    console.log(file);
  });
});

fs.readdirSync

const testFolder = './tests/';
const fs = require('fs');

fs.readdirSync(testFolder).forEach(file => {
  console.log(file);
});

2つの方法の違いは、最初の方法は非同期なので、読み取りプロセスが終了したときに実行されるコールバック関数を提供する必要があります。

2番目は同期的で、ファイル名の配列を返しますが、読み込み処理が終了するまでそれ以上のコードの実行は停止します。

1047
CMS

上記の答えはディレクトリへの再帰的な検索を実行しません。これが再帰的検索のために私がしたことです( node-walk を使って):npm install walk

var walk    = require('walk');
var files   = [];

// Walker options
var walker  = walk.walk('./test', { followLinks: false });

walker.on('file', function(root, stat, next) {
    // Add this file to the list of files
    files.Push(root + '/' + stat.name);
    next();
});

walker.on('end', function() {
    console.log(files);
});
173
Ruben Tan

IMOがそのようなタスクを実行する最も便利な方法は glob ツールを使うことです。これは globパッケージ のnode.jsです。と一緒にインストール

npm install glob

それからワイルドカードを使用してファイル名を一致させます(パッケージのWebサイトからの例)

var glob = require("glob")

// options is optional
glob("**/*.js", options, function (er, files) {
  // files is an array of filenames.
  // If the `nonull` option is set, and nothing
  // was found, then files is ["**/*.js"]
  // er is an error object or null.
})
172
KFL

すべてのサブディレクトリのファイルを取得する

function getFiles (dir, files_){
    files_ = files_ || [];
    var files = fs.readdirSync(dir);
    for (var i in files){
        var name = dir + '/' + files[i];
        if (fs.statSync(name).isDirectory()){
            getFiles(name, files_);
        } else {
            files_.Push(name);
        }
    }
    return files_;
}

console.log(getFiles('path/to/dir'))
81
Tito100

これはネイティブのfspathモジュールだけを使った簡単な解決法です:

// sync version
function walkSync(currentDirPath, callback) {
    var fs = require('fs'),
        path = require('path');
    fs.readdirSync(currentDirPath).forEach(function (name) {
        var filePath = path.join(currentDirPath, name);
        var stat = fs.statSync(filePath);
        if (stat.isFile()) {
            callback(filePath, stat);
        } else if (stat.isDirectory()) {
            walkSync(filePath, callback);
        }
    });
}

または非同期バージョン(代わりにfs.readdirを使用):

// async version with basic error handling
function walk(currentDirPath, callback) {
    var fs = require('fs'),
        path = require('path');
    fs.readdir(currentDirPath, function (err, files) {
        if (err) {
            throw new Error(err);
        }
        files.forEach(function (name) {
            var filePath = path.join(currentDirPath, name);
            var stat = fs.statSync(filePath);
            if (stat.isFile()) {
                callback(filePath, stat);
            } else if (stat.isDirectory()) {
                walk(filePath, callback);
            }
        });
    });
}

それからあなたはただ(同期版のために)電話をかけます:

walkSync('path/to/root/dir', function(filePath, stat) {
    // do something with "filePath"...
});

または非同期バージョン:

walk('path/to/root/dir', function(filePath, stat) {
    // do something with "filePath"...
});

違いは、IOの実行中にノードがブロックする方法にあります。上記のAPIが同じであることを考えると、最大のパフォーマンスを保証するために非同期バージョンを使用することができます。

ただし、同期バージョンを使用することには1つの利点があります。ウォークの後の次のステートメントのように、ウォークが完了したらすぐにコードを実行する方が簡単です。非同期バージョンでは、いつ完了したかを知るための追加の方法が必要になります。おそらく最初にすべてのパスのマップを作成し、次にそれらを列挙します。単純なbuild/utilスクリプト(高性能Webサーバーに対して)の場合は、損傷を与えずに同期バージョンを使用できます。

55
Ali

ES7でプロミスを使用する

Mz/fsとの非同期使用

mz モジュールはコアノードライブラリの有望バージョンを提供します。使い方は簡単です。最初にライブラリをインストールしてください...

npm install mz

それで….

const fs = require('mz/fs');
fs.readdir('./myDir').then(listing => console.log(listing))
  .catch(err => console.error(err));

あるいは、ES7の非同期関数でそれらを書くことができます。

async function myReaddir () {
  try {
    const file = await fs.readdir('./myDir/');
  }
  catch (err) { console.error( err ) }
};

再帰的リストの更新

何人かのユーザは再帰的リストを見たいという希望を指定しています(質問には含まれていません)... fs-promise を使用してください。 mz の周りの細いラッパーです。

npm install fs-promise;

それで….

const fs = require('fs-promise');
fs.walk('./myDir').then(
    listing => listing.forEach(file => console.log(file.path))
).catch(err => console.error(err));
23
Evan Carroll

依存関係

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

定義

// String -> [String]
function fileList(dir) {
  return fs.readdirSync(dir).reduce(function(list, file) {
    var name = path.join(dir, file);
    var isDir = fs.statSync(name).isDirectory();
    return list.concat(isDir ? fileList(name) : [name]);
  }, []);
}

使用法。

var DIR = '/usr/local/bin';

// 1. List all files in DIR
fileList(DIR);
// => ['/usr/local/bin/babel', '/usr/local/bin/bower', ...]

// 2. List all file names in DIR
fileList(DIR).map((file) => file.split(path.sep).slice(-1)[0]);
// => ['babel', 'bower', ...]

fileListは楽観的すぎるので注意してください。深刻な場合は、エラー処理を追加してください。

15
Hunan Rostomyan

再帰的に実行したいとは言わないので、ディレクトリの直接の子だけが必要だと思います。

サンプルコード

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

fs.readdirSync('your-directory-path')
  .filter((file) => fs.lstatSync(path.join(folder, file)).isFile());
10
Tyler Long

fsをロードする:

const fs = require('fs');

ファイルの読み取り 非同期

fs.readdir('./dir', function (err, files) {
    // "files" is an Array with files names
});

ファイルの読み取り 同期

var files = fs.readdirSync('./dir');
7
Eduardo Cuomo

sortedのファイル名を取得してください。 '.txt''.jpg'などの特定のextensionに基づいて結果をフィルタリングできます。

import * as fs from 'fs';
import * as Path from 'path';

function getFilenames(path, extension) {
    return fs
        .readdirSync(path)
        .filter(
            item =>
                fs.statSync(Path.join(path, item)).isFile() &&
                (extension === undefined || Path.extname(item) === extension)
        )
        .sort();
}
6
Yas

ノードv10.10.0以降、dirent.isDirectory()関数と組み合わせてfs.readdirおよびfs.readdirSyncに新しいwithFileTypesオプションを使用して、ディレクトリ内のファイル名をフィルタすることが可能です。それはこんな感じです:

fs.readdirSync('./dirpath', {withFileTypes: true})
.filter(item => !item.isDirectory())
.map(item => item.name)

返される配列は次の形式です。

['file1.txt', 'file2.txt', 'file3.txt']

fs.Direntクラスのドキュメント

4
bnp887

これが非同期再帰バージョンです。

    function ( path, callback){
     // the callback gets ( err, files) where files is an array of file names
     if( typeof callback !== 'function' ) return
     var
      result = []
      , files = [ path.replace( /\/\s*$/, '' ) ]
     function traverseFiles (){
      if( files.length ) {
       var name = files.shift()
       fs.stat(name, function( err, stats){
        if( err ){
         if( err.errno == 34 ) traverseFiles()
    // in case there's broken symbolic links or a bad path
    // skip file instead of sending error
         else callback(err)
        }
        else if ( stats.isDirectory() ) fs.readdir( name, function( err, files2 ){
         if( err ) callback(err)
         else {
          files = files2
           .map( function( file ){ return name + '/' + file } )
           .concat( files )
          traverseFiles()
         }
        })
        else{
         result.Push(name)
         traverseFiles()
        }
       })
      }
      else callback( null, result )
     }
     traverseFiles()
    }

まだ誰かがこれを探しているなら、私はこうします:

import fs from 'fs';
import path from 'path';

const getAllFiles = dir =>
    fs.readdirSync(dir).reduce((files, file) => {
        const name = path.join(dir, file);
        const isDirectory = fs.statSync(name).isDirectory();
        return isDirectory ? [...files, ...getAllFiles(name)] : [...files, name];
    }, []);

そしてその仕事は私にとってとても良い

3
Josh

@ Hunan-Rostomyanの一般的なアプローチを取り、より簡潔にしてexcludeDirs引数を追加しました。同じパターンに従うだけで、includeDirsで拡張するのは簡単です。

import * as fs from 'fs';
import * as path from 'path';

function fileList(dir, excludeDirs?) {
    return fs.readdirSync(dir).reduce(function (list, file) {
        const name = path.join(dir, file);
        if (fs.statSync(name).isDirectory()) {
            if (excludeDirs && excludeDirs.length) {
                excludeDirs = excludeDirs.map(d => path.normalize(d));
                const idx = name.indexOf(path.sep);
                const directory = name.slice(0, idx === -1 ? name.length : idx);
                if (excludeDirs.indexOf(directory) !== -1)
                    return list;
            }
            return list.concat(fileList(name, excludeDirs));
        }
        return list.concat([name]);
    }, []);
}

使用例

console.log(fileList('.', ['node_modules', 'typings', 'bower_components']));
3
A T

再帰的に実行することもできます。

これにはNPMモジュールがあります。

npm dree

これにより、ディレクトリツリーを文字列またはオブジェクトとして表現できます。ファイルコールバックを使用すると、目標を達成することもできます。必要に応じて、検討するファイル拡張子を指定することもできます。

これがコードです:

const dree = require('dree');

const fileNames = [];
const fileCb = function(file) {
    fileNames.Push(file.name);
}

dree.scan('path-to-directory', { extensions: [ 'html', 'js' ] }, fileCb);

console.log(fileNames); // All the html and js files inside the given folder and its subfolders
1
EuberDeveloper

これはTypeScriptで、オプションで再帰的で、オプションでエラーロギングと非同期ソリューションです。検索したいファイル名に正規表現を指定できます。

私はfs-extraを使いました、なぜならそれはfsの簡単なスーパーセットの改善だからです。

import * as FsExtra from 'fs-extra'

/**
 * Finds files in the folder that match filePattern, optionally passing back errors .
 * If folderDepth isn't specified, only the first level is searched. Otherwise anything up
 * to Infinity is supported.
 *
 * @static
 * @param {string} folder The folder to start in.
 * @param {string} [filePattern='.*'] A regular expression of the files you want to find.
 * @param {(Error[] | undefined)} [errors=undefined]
 * @param {number} [folderDepth=0]
 * @returns {Promise<string[]>}
 * @memberof FileHelper
 */
public static async findFiles(
    folder: string,
    filePattern: string = '.*',
    errors: Error[] | undefined = undefined,
    folderDepth: number = 0
): Promise<string[]> {
    const results: string[] = []

    // Get all files from the folder
    let items = await FsExtra.readdir(folder).catch(error => {
        if (errors) {
            errors.Push(error) // Save errors if we wish (e.g. folder perms issues)
        }

        return results
    })

    // Go through to the required depth and no further
    folderDepth = folderDepth - 1

    // Loop through the results, possibly recurse
    for (const item of items) {
        try {
            const fullPath = Path.join(folder, item)

            if (
                FsExtra.statSync(fullPath).isDirectory() &&
                folderDepth > -1)
            ) {
                // Its a folder, recursively get the child folders' files
                results.Push(
                    ...(await FileHelper.findFiles(fullPath, filePattern, errors, folderDepth))
                )
            } else {
                // Filter by the file name pattern, if there is one
                if (filePattern === '.*' || item.search(new RegExp(filePattern, 'i')) > -1) {
                    results.Push(fullPath)
                }
            }
        } catch (error) {
            if (errors) {
                errors.Push(error) // Save errors if we wish
            }
        }
    }

    return results
}
0
Paul F. Wood

npmlist-contents moduleを使用してください。与えられたディレクトリのコンテンツとサブコンテンツを読み込み、ファイルとフォルダのパスのリストを返します。

const list = require('list-contents');

list("./dist",(o)=>{
  if(o.error) throw o.error;
   console.log('Folders: ', o.dirs);
   console.log('Files: ', o.files);
});
0
Paweł

この作業を自動化するためのノードモジュールを作りました: mddir

使用法

ノードmddir "../relative/path/"

インストールするには:npm install mddir -g

現在のディレクトリにマークダウンを生成するには:mddir

絶対パス用に生成するには、次のように入力します。mddir/absolute/path

相対パス用に生成するには:mddir〜/ Documents/whatever。

Mdファイルが作業ディレクトリに生成されます。

現在、node_modules、および.gitフォルダは無視されます。

トラブルシューティング

'node\r:そのようなファイルまたはディレクトリがありません'というエラーが表示された場合、問題はオペレーティングシステムが異なる行末を使用していて、mddirが明示的に行末スタイルをUnixに設定しないと解析できないことです。これは通常Windowsだけでなく、Linuxのいくつかのバージョンにも影響します。改行コードをUNIX形式に設定するには、mddir npmグローバルbinフォルダ内で実行する必要があります。

行末修正

Npm binフォルダのパスを取得します。

npm config get prefix

そのフォルダにCd

インストールdos2unixを醸造しなさい

dos2unix lib/node_modules/mddir/src/mddir.js

これは、行末をDOSではなくUnixに変換します。

それから:node mddir "../relative/path/"で通常通りに実行してください。

生成されたマークダウンファイル構造の例 'directoryList.md'

    |-- .bowerrc
    |-- .jshintrc
    |-- .jshintrc2
    |-- Gruntfile.js
    |-- README.md
    |-- bower.json
    |-- karma.conf.js
    |-- package.json
    |-- app
        |-- app.js
        |-- db.js
        |-- directoryList.md
        |-- index.html
        |-- mddir.js
        |-- routing.js
        |-- server.js
        |-- _api
            |-- api.groups.js
            |-- api.posts.js
            |-- api.users.js
            |-- api.widgets.js
        |-- _components
            |-- directives
                |-- directives.module.js
                |-- vendor
                    |-- directive.draganddrop.js
            |-- helpers
                |-- helpers.module.js
                |-- proprietary
                    |-- factory.actionDispatcher.js
            |-- services
                |-- services.cardTemplates.js
                |-- services.cards.js
                |-- services.groups.js
                |-- services.posts.js
                |-- services.users.js
                |-- services.widgets.js
        |-- _mocks
            |-- mocks.groups.js
            |-- mocks.posts.js
            |-- mocks.users.js
            |-- mocks.widgets.js
0
John Byrne

ちょっと頭を上げてください。ディレクトリ内の各ファイルに対して操作を実行する予定の場合は、 vinyl-fs (ストリーミングビルドシステムの gulp で使用される)を試してください。

これにより、同じディレクトリにあるtest.txtファイルに結果が保存されます。

  fs.readdirSync(__dirname).forEach(file => {
    fs.appendFileSync("test.txt", file+"\n", function(err){
    })
})
0
Rama