javascript - ¿Cómo se obtiene una lista de los nombres de todos los archivos presentes en un directorio en Node.js?
Estoy intentando obtener una lista de los nombres de todos los archivos presentes en un directorio usando Node.js. Quiero que el resultado sea un array de nombres de archivos. ¿Cómo puedo hacer esto?
Respuesta #1
Puedes usar los métodos fs.readdir o fs.readdirSync. fs está incluido en el núcleo de Node.js, por lo que no es necesario instalar nada.
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 asincrónico, por lo que tienes que proporcionar una función de devolución de llamada que se ejecutará cuando finalice el proceso de lectura.
El segundo es síncrono, devolverá el arreglo de nombres de archivo, pero detendrá cualquier ejecución adicional de tu código hasta que termine el proceso de lectura.
Respuesta #2
En mi opinión, la forma más conveniente de realizar tales tareas es utilizar una herramienta glob. Aquí hay un paquete glob para node.js. Instálalo con
npm install glob
Luego usa comodines para coincidir con nombres de archivos (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.
})
Si planeas usar globby, aquí hay un ejemplo para buscar cualquier archivo xml que esté bajo la carpeta actual
var globby = require('globby');
const paths = await globby("**/*.xml");
Respuesta #3
A partir de Node v10.10.0, es posible usar la nueva opción withFileTypes para fs.readdir y fs.readdirSync en combinación con la función dirent.isDirectory() para filtrar nombres de archivos en un directorio. Eso se ve así:
fs.readdirSync('./dirpath', {withFileTypes: true})
.filter(item => !item.isDirectory())
.map(item => item.name)
El array devuelto está en la forma:
['file1.txt', 'file2.txt', 'file3.txt']
Respuesta #4
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);
});
Respuesta #5
Obtener archivos en todos los subdirectorios
const fs=require('fs');
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'))
Respuesta #6
Aquí hay una solución sencilla usando solo los módulos nativos fs y 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);
}
});
}
o versión asíncrona (usa fs.readdir en su 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);
}
});
});
}
Luego solo llamas (para la versión sincronizada):
walkSync('path/to/root/dir', function(filePath, stat) {
// do something with "filePath"...
});
o versión asincrónica:
walk('path/to/root/dir', function(filePath, stat) {
// do something with "filePath"...
});
La diferencia está en cómo el nodo se bloquea mientras realiza la E/S. Dado que la API anterior es la misma, podrías simplemente usar la versión asincrónica para asegurar el máximo rendimiento.
Sin embargo, hay una ventaja en usar la versión sincrónica. Es más fácil ejecutar algún código tan pronto como se termina el recorrido, como en la siguiente instrucción después del recorrido. Con la versión asíncrona, necesitarías una forma adicional de saber cuándo has terminado. Tal vez creando primero un mapa de todas las rutas y luego enumerándolas. Para scripts simples de construcción/utilidad (en comparación con servidores web de alto rendimiento), podrías usar la versión sincrónica sin causar ningún daño.
Respuesta #7
Usando Promesas con ES7
Uso asincrónico con mz/fs
El módulo mz proporciona versiones promisificadas de la biblioteca principal de Node. Usarlas 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, puedes escribirlos 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 un deseo de ver un listado recursivo (aunque no en la pregunta)... Usa fs-promise. Es un envoltorio ligero 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));
Respuesta #8
versión no recursiva
No dices que quieres hacerlo recursivamente, así que supongo que solo necesitas los hijos directos del directorio.
Código de ejemplo:
const fs = require('fs');
const path = require('path');
fs.readdirSync('your-directory-path')
.filter((file) => fs.lstatSync(path.join(folder, file)).isFile());
Respuesta #9
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 alguna gestión de errores.
Respuesta #10
Supongo por tu pregunta que no quieres nombres de directorios, solo archivos.
Ejemplo de estructura de directorios
animals
├── all.jpg
├── mammals
│ └── cat.jpg
│ └── dog.jpg
└── insects
└── bee.jpg
función Caminar
Los créditos van a Justin Maier en este gist
Si quieres solo un arreglo de las rutas de los archivos, usa return_object: false:
const fs = require('fs').promises;
const path = require('path');
async function walk(dir) {
let files = await fs.readdir(dir);
files = await Promise.all(files.map(async file => {
const filePath = path.join(dir, file);
const stats = await fs.stat(filePath);
if (stats.isDirectory()) return walk(filePath);
else if(stats.isFile()) return filePath;
}));
return files.reduce((all, folderContents) => all.concat(folderContents), []);
}
Uso
async function main() {
console.log(await walk('animals'))
}
Salida
[
"/animals/all.jpg",
"/animals/mammals/cat.jpg",
"/animals/mammals/dog.jpg",
"/animals/insects/bee.jpg"
];
Respuesta #11
son solo 2 líneas de código:
fs=require('fs')
fs.readdir("./img/", (err,filename)=>console.log(filename))
Imagen :
Respuesta #12
Cargar fs:
const fs = require('fs');
Leer archivos async:
fs.readdir('./dir', function (err, files) {
// "files" is an Array with files names
});
Leer archivos sincrónicamente:
var files = fs.readdirSync('./dir');
Respuesta #13
si alguien todavía busca esto, yo hago esto:
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];
}, []);y me funciona muy bien
Respuesta #14
Mi código de una línea:
const fs = require("fs")
const path = 'somePath/'
const filesArray = fs.readdirSync(path).filter(file => fs.lstatSync(path+file).isFile())
