جاوااسکریپت - چگونه میتوان فهرستی از نام همه فایلهای موجود در یک دایرکتوری در Node.js دریافت کرد؟
من در حال تلاش برای گرفتن لیستی از نام تمام فایلهای موجود در یک دایرکتوری با استفاده از Node.js هستم. من میخواهم خروجی به صورت یک آرایه از نام فایلها باشد. چگونه میتوانم این کار را انجام دهم؟
پاسخ شماره ۱
شما میتوانید از متدهای fs.readdir یا fs.readdirSync استفاده کنید. fs در هسته Node.js گنجانده شده است، بنابراین نیازی به نصب هیچ چیزی نیست.
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);
});
تفاوت بین این دو روش این است که روش اول ناهمزمان است، بنابراین شما باید یک تابع callback ارائه دهید که هنگام پایان فرایند خواندن اجرا شود.
دوم همزمان است، آرایه نام فایل را باز میگرداند، اما تا زمانی که فرآیند خواندن تمام نشده باشد، هر اجرای بعدی کد شما را متوقف میکند.
پاسخ شماره ۲
به نظر من راحتترین راه برای انجام چنین کارهایی استفاده از یک ابزار glob است. این یک بسته glob برای node.js است. نصب کنید با
npm install glob
سپس از کاراکتر جایگزین برای مطابقت با نام فایلها استفاده کنید (نمونهای از وبسایت بسته گرفته شده است)
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.
})
اگر شما برنامهریزی دارید از globby استفاده کنید، در اینجا یک مثال برای جستجوی هر فایل xml که در زیر پوشه فعلی است آورده شده است
var globby = require('globby');
const paths = await globby("**/*.xml");
پاسخ شماره ۳
از نسخه 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']
پاسخ شماره ۴
جواب بالا جستجوی بازگشتی در دایرکتوری را انجام نمیدهد. این کاری است که من برای یک جستجوی بازگشتی انجام دادم (با استفاده از 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);
});
پاسخ شماره ۵
دریافت فایلها در تمام زیرشاخهها
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'))
پاسخ شماره ۶
در اینجا یک راه حل ساده با استفاده از فقط ماژولهای بومی 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"...
});
تفاوت در این است که گره هنگام انجام ورودی/خروجی چگونه مسدود میشود. با توجه به اینکه API بالا یکسان است، میتوانید به سادگی از نسخه غیرهمزمان آن استفاده کنید تا حداکثر عملکرد را تضمین کنید.
با این حال، یک مزیت برای استفاده از نسخه همزمان وجود دارد. اجرای برخی کدها به محض اتمام پیمایش آسانتر است، همانطور که در دستور بعدی پس از پیمایش میبینیم. در نسخه غیرهمزمان، شما به روشی اضافی برای دانستن زمان اتمام نیاز دارید. شاید ابتدا ایجاد یک نقشه از همه مسیرها و سپس فهرست کردن آنها. برای اسکریپتهای ساده ساخت/ابزار (در مقابل سرورهای وب با عملکرد بالا) میتوانید از نسخه همزمان استفاده کنید بدون اینکه آسیبی وارد شود.
پاسخ شماره ۷
استفاده از پرامیسها با ES7
استفاده آسنکرون با mz/fs
ماژول mz نسخههای وعدهدار (promisified) از کتابخانه اصلی نود را فراهم میکند. استفاده از آنها ساده است. ابتدا کتابخانه را نصب کنید...
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));
پاسخ شماره ۸
نسخه غیر بازگشتی
شما نگفتید که میخواهید آن را به صورت بازگشتی انجام دهید، بنابراین من فرض میکنم که فقط به فرزندان مستقیم دایرکتوری نیاز دارید.
نمونه کد:
const fs = require('fs');
const path = require('path');
fs.readdirSync('your-directory-path')
.filter((file) => fs.lstatSync(path.join(folder, file)).isFile());
پاسخ شماره ۹
وابستگیها.
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 خیلی خوشبینانه است. برای هر چیز جدی، مقداری مدیریت خطا اضافه کنید.
پاسخ شماره ۱۰
من از سوالت حدس میزنم که تو نام پوشهها را نمیخوای، فقط فایلها را میخوای.
نمونه ساختار دایرکتوری
animals
├── all.jpg
├── mammals
│ └── cat.jpg
│ └── dog.jpg
└── insects
└── bee.jpg
تابع Walk
اعتبارات به جاستین مایر در این گیست تعلق دارد
اگر شما فقط یک آرایه از مسیرهای فایل میخواهید، از 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), []);
}
استفاده
async function main() {
console.log(await walk('animals'))
}
خروجی
[
"/animals/all.jpg",
"/animals/mammals/cat.jpg",
"/animals/mammals/dog.jpg",
"/animals/insects/bee.jpg"
];
پاسخ شماره ۱۱
این فقط ۲ خط کد است:
fs=require('fs')
fs.readdir("./img/", (err,filename)=>console.log(filename))
تصویر :
پاسخ شماره ۱۲
بارگذاری fs:
const fs = require('fs');
خواندن فایلها بهصورت غیرهمزمان:
fs.readdir('./dir', function (err, files) {
// "files" is an Array with files names
});
خواندن فایلها همزمان:
var files = fs.readdirSync('./dir');
پاسخ شماره ۱۳
اگر کسی هنوز دنبال این است، من این کار را میکنم:
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];
}, []);و کارش برای من خیلی خوب است
پاسخ شماره ۱۴
کد تک خطی من:
const fs = require("fs")
const path = 'somePath/'
const filesArray = fs.readdirSync(path).filter(file => fs.lstatSync(path+file).isFile())
