Я пытаюсь получить список имен всех файлов, присутствующих в каталоге, используя 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);
})
Разница между этими двумя методами заключается в том, что первый метод является асинхронным, поэтому вы должны предоставить функцию обратного вызова, которая будет выполняться после завершения процесса чтения.
Второй является синхронным, он вернет массив имен файлов, но остановит дальнейшее выполнение вашего кода, пока не завершится процесс чтения.
readdir
также показывает имена каталогов . Чтобы отфильтровать их, используйте fs.stat(path, callback(err, stats))
и stats.isDirectory()
.
IMO самым удобным способом выполнения таких задач является использование инструмента glob. Здесь glob-пакет для node.js. Установите с помощью
npm install glob
Затем используйте wild card для соответствия именам файлов (пример, взятый с веб-сайта пакета)
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.
})
В приведенном выше ответе не выполняется рекурсивный поиск в каталоге. Вот что я сделал для рекурсивного поиска (используя 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);
});
Получить файлы во всех поддиректорах
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'))
if (typeof files_ === 'undefined') files_=[];
? вам нужно только сделать var files_ = files_ || [];
вместо files_ = files_ || [];
,
Здесь простое решение, использующее только собственные 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"...
});
Разница заключается в том, как блокировать node при выполнении IO. Учитывая, что вышеприведенный API один и тот же, вы можете просто использовать версию async для обеспечения максимальной производительности.
Однако есть одно преимущество использования синхронной версии. Легче выполнить какой-то код, как только будет выполнена прогулка, как в следующем заявлении после прогулки. С асинхронной версией вам понадобится дополнительный способ узнать, когда вы закончите. Возможно сначала создать карту всех путей, а затем перечислить их. Для простых скриптов build/util (vs высокопроизводительных веб-серверов) вы можете использовать версию синхронизации без каких-либо повреждений.
walkSync
из walk(filePath, callback);
to walkSync(filePath, callback);
Модуль mz
предоставляет многообещающие версии основной библиотеки node. Использование их просто. Сначала установите библиотеку...
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]);
}, []);
}
Usage.
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
слишком оптимистичен. Для чего-нибудь серьезного, добавьте некоторые ошибки обработки.
excludeDirs
массива excludeDirs
. Это меняет его настолько, что, возможно, вы должны отредактировать его (если хотите). В противном случае я добавлю это в другом ответе. gist.github.com/AlecTaylor/f3f221b4fb86b4375650
Вы не говорите, что хотите сделать это рекурсивно, поэтому я предполагаю, что вам нужны только прямые дети из каталога.
Пример кода:
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');
Чтение файлов async:
fs.readdir('./dir', function (err, files) {
// "files" is an Array with files names
});
Чтение файлов:
var files = fs.readdirSync('./dir');
Здесь представлена асинхронная рекурсивная версия.
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 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()
}
Получить sorted
имена файлов. Вы можете фильтровать результаты по определенному extension
например, '.txt'
, '.jpg'
и так далее.
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();
}
Взял общий подход @Хунань-Ростомян, сделал его более лаконичным и добавил аргумент 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']));
Начиная с Node v10.10.0, можно использовать новую опцию withFileTypes
для fs.readdir
и fs.readdirSync
в сочетании с dirent.isDirectory()
для фильтрации имен файлов в каталоге. Это выглядит так:
fs.readdirSync('./dirpath', {withFileTypes: true})
.filter(item => !item.isDirectory())
.map(item => item.name)
Возвращенный массив имеет вид:
['file1.txt', 'file2.txt', 'file3.txt']
если кто-то все еще ищет это, я делаю это:
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];
}, []);
и его работа очень хорошо для меня
Используйте модуль списка содержимого npm
. Он читает содержимое и под-содержимое данного каталога и возвращает список путей к файлам и папкам.
const list = require('list-contents');
list("./dist",(o)=>{
if(o.error) throw o.error;
console.log('Folders: ', o.dirs);
console.log('Files: ', o.files);
});
Я сделал модуль node для автоматизации этой задачи: mddir
node 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 должна выполняться в глобальной папке bin mddir npm.
Получить путь к папке npm bin с помощью:
npm config get prefix
Cd в эту папку
brew установить dos2unix
dos2unix lib/ node_modules/mddir/src/mddir.js
Это преобразует окончание строк в Unix вместо Dos
Затем выполните как обычно: 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
function getFilesRecursiveSync(dir, fileList, optionalFilterFunction) {
if (!fileList) {
grunt.log.error("Variable 'fileList' is undefined or NULL.");
return;
}
var files = fs.readdirSync(dir);
for (var i in files) {
if (!files.hasOwnProperty(i)) continue;
var name = dir + '/' + files[i];
if (fs.statSync(name).isDirectory()) {
getFilesRecursiveSync(name, fileList, optionalFilterFunction);
} else {
if (optionalFilterFunction && optionalFilterFunction(name) !== true)
continue;
fileList.push(name);
}
}
}
fs.readdir
работает, но не может использовать шаблоны имен файлов, такие какls /tmp/*core*
. Проверьте github.com/isaacs/node-glob . Глобусы могут даже искать в подкаталогах.readdir-recursive
модульreaddir-recursive
хотя, если вы ищете имена файлов в подкаталогах, также