recursively read node files example directories current all javascript node.js directory-listing

javascript - read - ¿Cómo se obtiene una lista de los nombres de todos los archivos presentes en un directorio en Node.js?



node js count files in directory (16)

Usando Promesas con ES7

Uso asíncrono con mz / fs

El módulo mz proporciona versiones prometidas de la biblioteca de nodos centrales. Usarlos es simple. Primero instala la biblioteca ...

npm install mz

Entonces...

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

Alternativamente, puede escribirlas en funciones asíncronas en ES7:

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

Actualización para listado recursivo

Algunos de los usuarios han especificado el deseo de ver una lista recursiva (aunque no en la pregunta) ... Use fs-promise . Es una envoltura delgada alrededor de mz .

npm install fs-promise;

entonces...

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

Estoy tratando de obtener una lista de los nombres de todos los archivos presentes en un directorio usando Node.js. Quiero salida que es una matriz de nombres de archivos. ¿Cómo puedo hacer esto?


Aquí hay una solución simple utilizando solo los módulos de path y fs nativos:

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

o versión asíncrona (usa fs.readdir en fs.readdir lugar):

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

Entonces solo llamas (para la versión de sincronización):

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

o versión asíncrona:

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

La diferencia está en cómo se bloquea el nodo mientras se realiza el IO. Dado que la API anterior es la misma, puede usar la versión asíncrona para garantizar el máximo rendimiento.

Sin embargo, hay una ventaja de usar la versión síncrona. Es más fácil ejecutar un código tan pronto como se realiza la caminata, como en la siguiente declaración después de la caminata. Con la versión asíncrona, necesitaría alguna forma adicional de saber cuándo ha terminado. Quizás creando primero un mapa de todos los caminos, luego enumerándolos. Para los scripts de compilación / utilidad simples (frente a los servidores web de alto rendimiento), puede usar la versión de sincronización sin causar ningún daño.


Aquí hay una versión recursiva asíncrona.

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() }


Carga fs :

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

Leer archivos asíncronos :

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

Leer archivos sincronizados :

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


En mi opinión, la forma más conveniente de realizar estas tareas es utilizar una herramienta glob . Aquí hay un github.com/isaacs/node-glob global para node.js. Instalar con

npm install glob

Luego use el comodín para hacer coincidir los nombres de archivo (ejemplo tomado del sitio web del paquete)

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. })


Hice un módulo de nodo para automatizar esta tarea: mddir

Uso

nodo mddir "../relative/path/"

Para instalar: npm install mddir -g

Para generar rebajas para el directorio actual: mddir

Para generar para cualquier ruta absoluta: mddir / absolute / ruta

Para generar para una ruta relativa: mddir ~ / Documents / whatever.

El archivo md se genera en su directorio de trabajo.

Actualmente ignora los node_modules y las carpetas .git.

Solución de problemas

Si recibe el error ''nodo / r: No existe tal archivo o directorio'', el problema es que su sistema operativo usa diferentes finales de línea y mddir no puede analizarlos sin que usted establezca explícitamente el estilo de final de línea en Unix. Esto generalmente afecta a Windows, pero también a algunas versiones de Linux. La configuración de los finales de línea al estilo Unix debe realizarse dentro de la carpeta bin global de mddir npm.

Corrección de finales de línea

Obtenga la ruta de la carpeta bin npm con:

npm config get prefix

Cd en esa carpeta

brew install dos2unix

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

Esto convierte los finales de línea a Unix en lugar de Dos

Luego ejecute normalmente con: node mddir "../relative/path/".

Ejemplo de estructura de archivos de rebaja generada ''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


No dices que quieres hacerlo recursivamente, así que asumo que solo necesitas hijos directos del directorio.

Código de muestra:

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


Obtener archivos en todos los subdirectorios.

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


Obtener nombres de archivos sorted . Puede filtrar los resultados según una extension específica como ''.txt'' , ''.jpg'' y así sucesivamente.

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


Puede utilizar los métodos fs.readdir o 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); })

La diferencia entre los dos métodos es que el primero es asíncrono, por lo que debe proporcionar una función de devolución de llamada que se ejecutará cuando finalice el proceso de lectura.

El segundo es sincrónico, devolverá la matriz de nombre de archivo, pero detendrá cualquier ejecución adicional de su código hasta que finalice el proceso de lectura.


Sin embargo, la respuesta anterior no realiza una búsqueda recursiva en el directorio. Esto es lo que hice para una búsqueda recursiva (usando 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); });


Solo un aviso: si planea realizar operaciones en cada archivo en un directorio, pruebe vinyl-fs (que es utilizado por gulp , el sistema de compilación en tiempo real).


Tomó el enfoque general de @ Hunan-Rostomyan, lo hizo un poco más conciso y agregó el argumento excludeDirs . Sería trivial extender con includeDirs , solo sigue el mismo patrón:

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]); }, []); }

Ejemplo de uso:

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


Utilice el npm list-contents npm . Lee los contenidos y sub-contenidos del directorio dado y devuelve la lista de rutas de archivos y carpetas.

const list = require(''list-contents''); list("./dist",(o)=>{ if(o.error) throw o.error; console.log(''Folders: '', o.dirs); console.log(''Files: '', o.files); });


Dependencias.

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

Definición.

// 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]); }, []); }

Uso.

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'', ...]

Tenga en cuenta que fileList es demasiado optimista. Para cualquier cosa seria, agregue algún manejo de errores.


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