Node.jsを使ってディレクトリに存在するすべてのファイルの名前のリストを取得しようとしています。出力がファイル名の配列であることを望みます。これどうやってするの?
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番目は同期的で、ファイル名の配列を返しますが、読み込み処理が終了するまでそれ以上のコードの実行は停止します。
上記の答えはディレクトリへの再帰的な検索を実行しません。これが再帰的検索のために私がしたことです( 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);
});
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.
})
すべてのサブディレクトリのファイルを取得する
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'))
これはネイティブのfs
とpath
モジュールだけを使った簡単な解決法です:
// 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サーバーに対して)の場合は、損傷を与えずに同期バージョンを使用できます。
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));
依存関係
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
は楽観的すぎるので注意してください。深刻な場合は、エラー処理を追加してください。
再帰的に実行したいとは言わないので、ディレクトリの直接の子だけが必要だと思います。
サンプルコード
const fs = require('fs');
const path = require('path');
fs.readdirSync('your-directory-path')
.filter((file) => fs.lstatSync(path.join(folder, file)).isFile());
fs
をロードする:
const fs = require('fs');
ファイルの読み取り 非同期 :
fs.readdir('./dir', function (err, files) {
// "files" is an Array with files names
});
ファイルの読み取り 同期 :
var files = fs.readdirSync('./dir');
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();
}
ノード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']
これが非同期再帰バージョンです。
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];
}, []);
そしてその仕事は私にとってとても良い
@ 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']));
再帰的に実行することもできます。
これにはNPMモジュールがあります。
これにより、ディレクトリツリーを文字列またはオブジェクトとして表現できます。ファイルコールバックを使用すると、目標を達成することもできます。必要に応じて、検討するファイル拡張子を指定することもできます。
これがコードです:
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
これは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
}
npm
list-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);
});
この作業を自動化するためのノードモジュールを作りました: 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/"で通常通りに実行してください。
|-- .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
これにより、同じディレクトリにあるtest.txtファイルに結果が保存されます。
fs.readdirSync(__dirname).forEach(file => {
fs.appendFileSync("test.txt", file+"\n", function(err){
})
})