Pada dasarnya ada dua cara untuk mencapai ini. Dalam lingkungan async Anda akan melihat bahwa ada dua jenis loop: serial dan paralel. Serial loop menunggu satu iterasi untuk diselesaikan sebelum berpindah ke iterasi berikutnya - ini menjamin bahwa setiap iterasi loop selesai secara berurutan. Dalam loop paralel, semua iterasi dimulai pada waktu yang sama, dan satu dapat menyelesaikan sebelum yang lain, namun, itu jauh lebih cepat daripada loop serial. Jadi dalam hal ini, mungkin lebih baik menggunakan loop paralel karena tidak masalah urutan jalannya selesai, asalkan selesai dan mengembalikan hasilnya (kecuali jika Anda menginginkannya secara berurutan).
Loop paralel akan terlihat seperti ini:
var fs = require('fs');
var path = require('path');
var walk = function(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err) return done(err);
var pending = list.length;
if (!pending) return done(null, results);
list.forEach(function(file) {
file = path.resolve(dir, file);
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
walk(file, function(err, res) {
results = results.concat(res);
if (!--pending) done(null, results);
});
} else {
results.push(file);
if (!--pending) done(null, results);
}
});
});
});
};
Serial loop akan terlihat seperti ini:
var fs = require('fs');
var path = require('path');
var walk = function(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err) return done(err);
var i = 0;
(function next() {
var file = list[i++];
if (!file) return done(null, results);
file = path.resolve(dir, file);
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
walk(file, function(err, res) {
results = results.concat(res);
next();
});
} else {
results.push(file);
next();
}
});
})();
});
};
Dan untuk mengujinya di direktori home Anda (PERINGATAN: daftar hasil akan sangat besar jika Anda memiliki banyak hal di direktori home Anda):
walk(process.env.HOME, function(err, results) {
if (err) throw err;
console.log(results);
});
EDIT: Contoh yang ditingkatkan.
file = dir + '/' + file;
Ini tidak disarankan. Anda harus menggunakan:var path = require('path'); file = path.resolve(dir, file);
path.resolve(...)
Anda akan mendapatkan jalur yang tepat apakah Anda berada di Windows atau Unix :) Berarti Anda akan mendapatkan sesuatu sepertiC:\\some\\foo\\path
di Windows dan/some/foo/path
pada sistem Unixrequire('node-dir').files(__dirname, function(err, files) { console.log(files); });
!--
sintaksis, sebuah pertanyaan telah diajukan tentang hal ituYang ini menggunakan jumlah maksimum baru, fitur buzzwordy yang tersedia di node 8, termasuk Janji, util / promisifikasi, perusakan, menunggu async, peta + kurangi dan banyak lagi, membuat rekan kerja Anda menggaruk-garuk kepala saat mereka mencoba mencari tahu apa sedang terjadi.
Node 8+
Tidak ada ketergantungan eksternal.
Pemakaian
Node 10.10+
Diperbarui untuk node 10+ dengan whizbang lebih banyak:
Perhatikan bahwa mulai dengan simpul 11.15.0 Anda dapat menggunakan
files.flat()
alih-alihArray.prototype.concat(...files)
untuk meratakan array file.Node 11+
Jika Anda ingin meledakkan kepala semua orang sepenuhnya, Anda dapat menggunakan versi berikut menggunakan iterator async . Selain menjadi sangat keren, ini juga memungkinkan konsumen untuk menarik hasil satu per satu, sehingga lebih cocok untuk direktori yang sangat besar.
Penggunaan telah berubah karena tipe pengembalian sekarang merupakan iterator async bukan janji
Jika seseorang tertarik, saya telah menulis lebih banyak tentang iterator async di sini: https://qwtel.com/posts/software/async-generators-in-the-wild/
sumber
subdir
dansubdirs
menyesatkan, karena mereka mungkin benar-benar file (saya sarankan sesuatu sepertiitemInDir
atauitem_in_dir
atau bahkan hanyaitem
sebagai gantinya.), Tetapi solusi ini terasa lebih bersih daripada yang diterima dan kode jauh lebih sedikit. Saya juga tidak merasa jauh lebih rumit daripada kode dalam jawaban yang diterima. +1require(fs).promises
dan hanya menjatuhkanutil.promisify
sepenuhnya. Secara pribadi saya alias fs ke fs.promises.readdir
AKA objek pilihan seperti jadireaddir(dir, {withFileTypes: true})
ini akan mengembalikan semua item dengan informasi tipenya, jadi kita tidak perlu meneleponstat
sama sekali untuk mendapatkan informasi yangreaddir
sekarang memberi kita kembali. Ini menyelamatkan kita dari keharusan membuat panggilan sistem tambahan. Detail di siniwithFileTypes
. Terima kasih atas tipnya.return Array.prototype.concat(...files);
denganlet result = Array.prototype.concat(...files); return result.map(file => file.split('\\').join('/'));
Anda dapat memastikan dirs mengembalikan "/" dan bukan "\". Jika Anda tidak keberatan dengan regex, Anda juga dapat melakukannyareturn result.map(file => file.replace(/\\/g, '/'));
Kalau-kalau ada yang merasa berguna, saya juga membuat versi sinkron .
Kiat: Untuk menggunakan lebih sedikit sumber daya saat memfilter. Saring di dalam fungsi ini sendiri. Misalnya Ganti
results.push(file);
dengan kode di bawah ini. Sesuaikan sesuai kebutuhan:sumber
lstat
sebagai gantinya? Atau tambahkan cek rekursif untuk membatasi tingkat rekursif.A. Lihat modul file . Ini memiliki fungsi yang disebut berjalan:
Ini mungkin untukmu! Dan ya, itu async. Namun, saya pikir Anda harus mengumpulkan sendiri jalur lengkapnya, jika Anda membutuhkannya.
B. Alternatif, dan bahkan salah satu favorit saya: gunakan unix
find
untuk itu. Mengapa melakukan sesuatu lagi, yang sudah diprogram? Mungkin tidak persis apa yang Anda butuhkan, tetapi masih layak untuk dicoba:Find memiliki mekanisme caching bawaan yang bagus yang membuat pencarian berikutnya sangat cepat, selama hanya beberapa folder yang berubah.
sumber
Paket npm yang bagus adalah glob .
npm install glob
Ini sangat kuat dan harus mencakup semua kebutuhan berulang Anda.
Edit:
Saya sebenarnya tidak sepenuhnya senang dengan glob, jadi saya membuat readdirp .
Saya sangat yakin bahwa API-nya membuat pencarian file dan direktori secara rekursif dan menerapkan filter spesifik menjadi sangat mudah.
Bacalah dokumentasinya untuk mendapatkan ide yang lebih baik tentang apa yang dilakukannya dan instal melalui:
npm install readdirp
sumber
Saya sarankan menggunakan node-glob untuk menyelesaikan tugas itu.
sumber
Jika Anda ingin menggunakan paket npm, kunci pas cukup bagus.
EDIT (2018):
Siapa pun yang membaca dalam waktu terakhir: Penulis mencabut paket ini pada tahun 2015:
sumber
denodify
ini? Callback dipecat beberapa kali (secara rekursif). Jadi menggunakanQ.denodify(wrench.readdirRecursive)
pengembalian hanya hasil pertama.Saya menyukai jawaban dari chjj di atas dan tidak akan dapat membuat versi saya dari loop paralel tanpa permulaan itu.
Saya membuat intisari juga. Komentar diterima. Saya masih memulai di ranah NodeJS sehingga itu adalah salah satu cara saya berharap untuk belajar lebih banyak.
sumber
Dengan Rekursi
Panggilan
sumber
/
tetapi menggunakanpath
modul:path.join(searchPath, file)
. Dengan begitu, Anda akan mendapatkan jalur yang benar terlepas dari OS.Gunakan node-dir untuk menghasilkan output yang Anda suka
sumber
Saya telah mengkodekan ini baru-baru ini, dan berpikir akan masuk akal untuk membagikan ini di sini. Kode memanfaatkan perpustakaan async .
Anda bisa menggunakannya seperti ini:
sumber
Perpustakaan yang disebut Filehound adalah pilihan lain. Ini akan secara rekursif mencari direktori yang diberikan (direktori kerja secara default). Ini mendukung berbagai filter, panggilan balik, janji dan sinkronisasi pencarian.
Misalnya, cari direktori kerja saat ini untuk semua file (menggunakan panggilan balik):
Atau menjanjikan dan menentukan direktori tertentu:
Konsultasikan dengan dokumen untuk kasus penggunaan lebih lanjut dan contoh penggunaan: https://github.com/nspragg/filehound
Penafian: Saya penulis.
sumber
Menggunakan async / menunggu, ini seharusnya bekerja:
Anda dapat menggunakan bluebird. Promisikan atau ini:
Lihat jawaban saya yang lain untuk pendekatan generator yang dapat memberikan hasil lebih cepat.
sumber
Async
Sinkronkan
Dapat dibaca Async
Catatan: kedua versi akan mengikuti symlink (sama seperti aslinya
fs.readdir
)sumber
Lihatlah perpustakaan final-fs . Ini menyediakan
readdirRecursive
fungsi:sumber
Implementasi janji mandiri
Saya menggunakan perpustakaan when.js berjanji dalam contoh ini.
Saya telah memasukkan parameter opsional
includeDir
yang akan menyertakan direktori dalam daftar file jika diatur ketrue
.sumber
klaw dan klaw-sync patut dipertimbangkan untuk hal semacam ini. Ini adalah bagian dari node-fs-extra .
sumber
Inilah implementasi lain . Tak satu pun dari solusi di atas memiliki pembatas, dan jadi jika struktur direktori Anda besar, mereka semua akan meronta-ronta dan akhirnya kehabisan sumber daya.
Menggunakan konkurensi 50 berfungsi dengan baik, dan hampir secepat implementasi sederhana untuk struktur direktori kecil.
sumber
The rekursif-readdir modul memiliki fungsi ini.
sumber
Saya memodifikasi jawaban berdasarkan Trevor Senior's Promise untuk bekerja dengan Bluebird
sumber
Untuk bersenang-senang, berikut adalah versi berbasis aliran yang bekerja dengan perpustakaan aliran highland.js. Itu ditulis bersama oleh Victor Vu.
sumber
Menggunakan Janji ( Q ) untuk menyelesaikan ini dalam gaya Fungsional:
Ini mengembalikan janji array, sehingga Anda dapat menggunakannya sebagai:
sumber
Saya harus menambahkan perpustakaan sander berbasis Janji ke daftar.
sumber
Menggunakan bluebird janji.coroutine:
sumber
Karena setiap orang harus menulis sendiri, saya membuatnya.
walk (dir, cb, endCb) cb (file) endCb (err | null)
KOTOR
sumber
lihat loaddir https://npmjs.org/package/loaddir
npm install loaddir
Anda dapat menggunakan
fileName
alih-alihbaseName
jika Anda membutuhkan ekstensi juga.Bonus tambahan adalah bahwa ia akan menonton file juga dan memanggil panggilan balik lagi. Ada banyak opsi konfigurasi untuk membuatnya sangat fleksibel.
Saya baru saja membuat ulang
guard
permata dari ruby menggunakan loaddir dalam waktu singkatsumber
Ini jawaban saya. Semoga bisa membantu seseorang.
Fokus saya adalah membuat pencarian rutin dapat berhenti di mana saja, dan untuk file yang ditemukan, memberitahu kedalaman relatif ke jalur asli.
sumber
Berikut adalah metode rekursif untuk mendapatkan semua file termasuk subdirektori.
sumber
Satu lagi yang sederhana dan bermanfaat
sumber
Ini adalah bagaimana saya menggunakan fungsi nodejs fs.readdir untuk mencari direktori secara rekursif.
Katakanlah Anda memiliki jalur yang disebut '/ database' di root proyek simpul Anda. Setelah janji ini terselesaikan, harus memunculkan array dari setiap file di bawah '/ database'.
sumber