node.js fs.readdir পুনরাবৃত্ত ডিরেক্টরি অনুসন্ধান


266

Fs.readdir ব্যবহার করে async ডিরেক্টরি অনুসন্ধানের কোনও ধারণা? আমি বুঝতে পারি যে আমরা পুনরাবৃত্তি প্রবর্তন করতে পারি এবং পড়ার জন্য পরবর্তী ডিরেক্টরি সহ পঠন ডিরেক্টরি ফাংশনটি কল করতে পারি, তবে এটি অ্যাসিঙ্ক না হওয়ায় কিছুটা চিন্তিত ...

কোন ধারনা? আমি নোড-ওয়াকের দিকে নজর রেখেছি যা দুর্দান্ত, তবে রেডডির মতো আমাকে অ্যারেতে কেবল ফাইলগুলি দেয় না। যদিও

যেমন আউটপুট খুঁজছেন ...

['file1.txt', 'file2.txt', 'dir/file3.txt']

উত্তর:


378

এটি সম্পাদন করার মূলত দুটি উপায় রয়েছে। একটি অ্যাসিঙ্ক পরিবেশে আপনি লক্ষ্য করবেন যে দুটি ধরণের লুপ রয়েছে: সিরিয়াল এবং সমান্তরাল। সিরিয়াল লুপটি পরবর্তী পুনরাবৃত্তির দিকে চলে যাওয়ার আগে একটি পুনরাবৃত্তি সম্পন্ন হওয়ার জন্য অপেক্ষা করে - এটি গ্যারান্টি দেয় যে লুপটির প্রতিটি পুনরাবৃত্তি ক্রম অনুসারে সম্পন্ন হয়। একটি সমান্তরাল লুপে, সমস্ত পুনরাবৃত্তি একই সময়ে শুরু হয় এবং একের আগে অন্যটির সম্পূর্ণ হতে পারে তবে এটি সিরিয়াল লুপের চেয়ে অনেক দ্রুত। সুতরাং এই ক্ষেত্রে, সমান্তরাল লুপটি ব্যবহার করা ভাল because কারণ এটি যতক্ষণ পদক্ষেপটি সম্পন্ন করে এবং ফলাফলগুলি ফেরত দেয় (যতক্ষণ না আপনি সেগুলি না চান) যতক্ষণ না হাঁটাটি কোন অর্ডারটি সম্পন্ন করে তা বিবেচনা করে না।

একটি সমান্তরাল লুপ দেখতে হবে:

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

একটি সিরিয়াল লুপ দেখতে হবে:

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

এবং এটি আপনার হোম ডিরেক্টরিতে পরীক্ষা করার জন্য (সতর্কতা: আপনার বাড়ির ডিরেক্টরিতে যদি প্রচুর পরিমাণে জিনিস থাকে তবে ফলাফলের তালিকাটি বিশাল হবে):

walk(process.env.HOME, function(err, results) {
  if (err) throw err;
  console.log(results);
});

সম্পাদনা: উন্নত উদাহরণ।


10
সাবধান, উপরের চিজজ থেকে "সমান্তরাল লুপ" উত্তরের ক্ষেত্রে খালি ফোল্ডারটি চলার ক্ষেত্রে একটি বাগ রয়েছে। ফিক্সটি হ'ল: var प्रलंबित = list.length; যদি (! মুলতুবি) সম্পন্ন (নাল, ফলাফল); // এই লাইন যুক্ত করুন! list.forEach (ফাংশন (ফাইল) {...
ভাসিল

27
file = dir + '/' + file;এটি সুপারিশ করা হয় না। আপনার ব্যবহার করা উচিত: var path = require('path'); file = path.resolve(dir, file);
লাইকো

7
@ অ্যানট্রিকপনি কারণ আপনি যদি ব্যবহার করেন তবে আপনি path.resolve(...)উইন্ডোজ বা ইউনিক্সে থাকাকালীন একটি সঠিক পথ পাবেন :) এর অর্থ আপনি C:\\some\\foo\\pathউইন্ডোজ এবং /some/foo/pathইউনিক্স সিস্টেমে কিছু পাবেন
Leiko

19
আমি নিম্নোক্ত হয়েছি কারণ আপনার উত্তরটি দুর্দান্ত ছিল যখন আপনি এটি প্রথম লিখেছিলেন ২০১১ সালে, তবে ২০১৪ সালে লোকেরা ওপেন সোর্স মডিউলগুলি ব্যবহার করে এবং নিজেরাই কম কোড লেখেন এবং মডিউলগুলিতে অবদান রাখেন যা তারা এবং অন্যান্য অনেক লোক নির্ভর করে। উদাহরণস্বরূপ নোড-ডির চেষ্টা করুন এই কোডের লাইনটি ব্যবহার করে @ ক্র্যাফ দ্বারা প্রয়োজনীয় আউটপুটটি পেতে:require('node-dir').files(__dirname, function(err, files) { console.log(files); });
ক্রিশ্চিয়ান ওয়েস্টারবিেক

5
!--সিনট্যাক্স সম্পর্কে যে কেউ বিভ্রান্ত হয়েছে, তার সম্পর্কে একটি প্রশ্ন জিজ্ঞাসা করা হয়েছে
তাস

145

প্রতিশ্রুতি, ব্যবহার / প্রতিশ্রুতি, ধ্বংসাত্মক কাঠামো, অ্যাসিঙ্ক-প্রতীক্ষা, মানচিত্র + হ্রাস এবং আরও অনেকগুলি সহ নোড 8-এ এটি সর্বাধিক পরিমাণে নতুন, গুজবর্ধক বৈশিষ্ট্যগুলি ব্যবহার করে যা আপনার সহকর্মীরা তাদের মাথাগুলি স্ক্র্যাচ করে তোলে তারা কী কী তা বের করার চেষ্টা করার সাথে সাথে? চলছে.

নোড 8+

বাহ্যিক নির্ভরতা নেই।

const { promisify } = require('util');
const { resolve } = require('path');
const fs = require('fs');
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);

async function getFiles(dir) {
  const subdirs = await readdir(dir);
  const files = await Promise.all(subdirs.map(async (subdir) => {
    const res = resolve(dir, subdir);
    return (await stat(res)).isDirectory() ? getFiles(res) : res;
  }));
  return files.reduce((a, f) => a.concat(f), []);
}

ব্যবহার

getFiles(__dirname)
  .then(files => console.log(files))
  .catch(e => console.error(e));

নোড 10.10+

আরও বেশি হুইসবাং সহ নোড 10+ এর জন্য আপডেট করা হয়েছে:

const { resolve } = require('path');
const { readdir } = require('fs').promises;

async function getFiles(dir) {
  const dirents = await readdir(dir, { withFileTypes: true });
  const files = await Promise.all(dirents.map((dirent) => {
    const res = resolve(dir, dirent.name);
    return dirent.isDirectory() ? getFiles(res) : res;
  }));
  return Array.prototype.concat(...files);
}

নোট 11.15.0 দিয়ে শুরু করে আপনি ফাইল অ্যারে সমতল করার files.flat()পরিবর্তে ব্যবহার করতে পারেন Array.prototype.concat(...files)

নোড 11+

আপনি যদি সবার মাথা পুরোপুরি উড়িয়ে দিতে চান তবে আপনি async পুনরুক্তি ব্যবহার করে নিম্নলিখিত সংস্করণটি ব্যবহার করতে পারেন । প্রকৃতপক্ষে শীতল হওয়ার পাশাপাশি এটি গ্রাহকরা একযোগে ফলাফল একবারে বের করে আনতে সহায়তা করে, এটি সত্যিকারের বৃহত ডিরেক্টরিগুলির জন্য আরও উপযুক্ত করে তোলে।

const { resolve } = require('path');
const { readdir } = require('fs').promises;

async function* getFiles(dir) {
  const dirents = await readdir(dir, { withFileTypes: true });
  for (const dirent of dirents) {
    const res = resolve(dir, dirent.name);
    if (dirent.isDirectory()) {
      yield* getFiles(res);
    } else {
      yield res;
    }
  }
}

ব্যবহারের পরিবর্তন হয়েছে কারণ প্রত্যাবর্তনের ধরণটি এখন প্রতিশ্রুতির পরিবর্তে একটি অ্যাসিঙ্ক পুনরাবৃত্তকারী

(async () => {
  for await (const f of getFiles('.')) {
    console.log(f);
  }
})()

যদি কেউ আগ্রহী হন তবে আমি এখানে async পুনরাবৃত্তকারীদের সম্পর্কে আরও লিখেছি: https://qwtel.com/posts/software/async-generators-in-the-wild/


5
এর নামকরণ subdirএবং subdirsবিভ্রান্তিকর করা হয়, তখন আসলে ফাইল হতে পারে (আমি ভালো কিছু সুপারিশ itemInDirবা item_in_dirবা এমনকি কেবল itemপরিবর্তে।), কিন্তু এই সমাধান গৃহীত এক তুলনায় ক্লিনার মতানুযায়ী এবং অনেক কম কোড। আমি স্বীকৃত উত্তরের কোডের চেয়েও বেশি জটিল দেখতে পাই না। +1
জেলফির কালটসটহল

1
আপনি require(fs).promisesএটি ব্যবহার করে আরও পুরোপুরি ড্রপ করে আরও হুইসবাং তৈরি করতে পারেন util.promisify। ব্যক্তিগতভাবে আমি ওরফে fs থেকে fs.promises।
মুশিননশিন

2
আমরা এটিকে একটি ছোট পরিবর্তনের মাধ্যমে দ্রুততর করতে পারি: একে একে readdirবিকল্প হিসাবে দ্বিতীয় যুক্তিটি পাস করার ফলে বিকল্প readdir(dir, {withFileTypes: true})ধরণের তথ্য দিয়ে এটি সমস্ত আইটেম ফিরিয়ে দেবে, সুতরাং এখন আমাদের statযে তথ্য readdirদেয় তা প্রাপ্ত করার জন্য আমাদের কোনও কল করতে হবে না পেছনে. এটি আমাদের অতিরিক্ত এস কল করার প্রয়োজন থেকে বাঁচায়।
বিশদগুলি

1
অন্তর্ভুক্ত করার জন্য @ ক্যাকোডার আপডেট হয়েছে withFileTypes। বখশিশের জন্য ধন্যবাদ.
qwtel

নোড ১০.১০+ তে, আপনি যদি প্রতিস্থাপন return Array.prototype.concat(...files);করেন তবে আপনারা let result = Array.prototype.concat(...files); return result.map(file => file.split('\\').join('/'));নিশ্চিত করতে পারেন যে ডায়াররা "/" ফিরিয়ে দেয় এবং "return" নয়। আপনি যদি return result.map(file => file.replace(/\\/g, '/'));
রেজেক্সকে

106

যদি কারও কাছে এটি দরকারী মনে হয় তবে আমি একটি সিঙ্ক্রোনাস সংস্করণও একসাথে রেখেছি ।

var walk = function(dir) {
    var results = [];
    var list = fs.readdirSync(dir);
    list.forEach(function(file) {
        file = dir + '/' + file;
        var stat = fs.statSync(file);
        if (stat && stat.isDirectory()) { 
            /* Recurse into a subdirectory */
            results = results.concat(walk(file));
        } else { 
            /* Is a file */
            results.push(file);
        }
    });
    return results;
}

টিপ: ফিল্টারিং করার সময় কম সংস্থান ব্যবহার করতে। এই ফাংশন মধ্যেই ফিল্টার। যেমন results.push(file);নীচের কোড দিয়ে প্রতিস্থাপন করুন । প্রয়োজনীয় হিসাবে সামঞ্জস্য করুন:

    file_type = file.split(".").pop();
    file_name = file.split(/(\\|\/)/g).pop();
    if (file_type == "json") results.push(file);

60
আমি এই সমাধানটি পছন্দ করি, আপনার আধা-কলোনগুলির অভাব বাদে!
এমপেন

এটি সহজ। তবে কিছুটা নির্বোধও। কোনও ডিরেক্টরিতে যদি কোনও প্যারেন্ট ডিরেক্টরিতে লিঙ্ক থাকে তবে স্ট্যাকওভারফ্লো তৈরি করতে পারে। lstatপরিবর্তে ব্যবহার করতে পারেন ? অথবা অন্যথায় পুনরাবৃত্তির মাত্রা সীমাবদ্ধ করতে পুনরাবৃত্তির চেক যোগ করুন।
conradkleinespel

14
ফাইল = প্রয়োজন ("পথ") ব্যবহার করে বিবেচনা করুন join যোগ দিন (দির, ফাইল)
এমকেমিওনার

16
@ এমপিেন সেমি-কলোনগুলি অতিরিক্ত কাজ করছে
অ্যালি

এটি আমার পক্ষে সবচেয়ে ভাল কাজ করে। যদিও আমি একটি নির্দিষ্ট ফাইল এক্সটেনশনের জন্য ফিল্টার করতে একটি ফিল্টার যুক্ত করেছি।
ব্রায়ান

87

উ: কটাক্ষপাত আছে ফাইল মডিউল । এটি ওয়াক নামে একটি ফাংশন রয়েছে:

ফাইল.ওয়াক (শুরু, কলব্যাক)

(নাল, dirPath, ডায়ার্স, ফাইল) পাস করে প্রতিটি ডিরেক্টরিতে কলব্যাক কল করে একটি ফাইল ট্রি নেভিগেট করে।

এটি আপনার জন্য হতে পারে! এবং হ্যাঁ, এটি অ্যাসিঙ্ক। তবে আমি মনে করি আপনার যদি প্রয়োজন হয় তবে আপনাকে পুরো পথটি নিজেই একত্রিত করতে হবে।

বি। বিকল্প এবং এমনকি আমার পছন্দের একটি: তার জন্য ইউনিক্স ব্যবহার করুন find। ইতিমধ্যে প্রোগ্রাম করা হয়েছে কেন কেন আবার কিছু করবেন? আপনার যা প্রয়োজন ঠিক তা না হলেও এটি যাচাইয়ের জন্য এখনও মূল্যবান:

var execFile = require('child_process').execFile;
execFile('find', [ 'somepath/' ], function(err, stdout, stderr) {
  var file_list = stdout.split('\n');
  /* now you've got a list with full path file names */
});

ফাইন্ডে একটি বিল্ট-ইন ক্যাশিং মেকানিজম রয়েছে যা পরবর্তী অনুসন্ধানগুলি খুব দ্রুত করে তোলে, যতক্ষণ না খুব কম ফোল্ডার বদলেছে।


9
এটি কি কেবল ইউনিক্স?
মোহসেন

উদাহরণস্বরূপ বি সম্পর্কে একটি প্রশ্ন ছিল: এক্সকিফিলের জন্য () এবং এক্সিকিউট ()) স্ট্যাডার এবং স্টাডআউট হ'ল বাফারস .. সুতরাং বাফার স্ট্রিং না হওয়ায় আপনার কি স্টডআউট.টো স্ট্রিং.স্প্লিট ("\ n") করার দরকার নেই?
চেরুভিম

8
দুর্দান্ত, তবে ক্রস প্ল্যাটফর্ম নয়।
f0ster

যাইহোক: না, এ কেবল ইউনিক্স নয়! কেবল বি কেবল ইউনিক্স। তবে উইন্ডোজ 10 এখন একটি লিনাক্স সাবসিস্টেম নিয়ে আসে with এমনকি বি আজকাল কেবল উইন্ডোজে কাজ করবে।
জোহান ফিলিপ স্ট্রাতাউসন

উইন্ডোজটিতে কাজ করার জন্য ডাব্লুএসএলকে শেষ ব্যবহারকারী পিসিতে সক্ষম করতে হবে ??
oldboy

38

আর একটি দুর্দান্ত এনপিএম প্যাকেজ গ্লোব

npm install glob

এটি খুব শক্তিশালী এবং আপনার সমস্ত পুনরাবৃত্তি প্রয়োজনগুলি আবরণ করা উচিত।

সম্পাদনা:

আমি আসলে গ্লোব নিয়ে পুরোপুরি খুশি ছিলাম না, তাই আমি পুনর্নির্মাণটি তৈরি করেছিলাম

আমি খুব আত্মবিশ্বাসী যে এর এপিআই ফাইল এবং ডিরেক্টরিগুলি পুনরাবৃত্তভাবে সন্ধান করে এবং নির্দিষ্ট ফিল্টার প্রয়োগ করা খুব সহজ করে তোলে।

এটি কী করে সে সম্পর্কে আরও ভাল ধারণা পেতে এর মাধ্যমে ডকুমেন্টেশনের মাধ্যমে পড়ুন এবং এর মাধ্যমে ইনস্টল করুন:

npm install readdirp


আমার মতে সেরা মডিউল । এবং গ্রান্ট, মোচা ইত্যাদি এবং অন্যান্য 80'000 + অন্যান্য প্রকল্পগুলির মতো আরও অনেক প্রকল্প ike কথা মাত্র.
ইয়ানিক রোচন


14

আপনি যদি এনপিএম প্যাকেজটি ব্যবহার করতে চান তবে রেঞ্চটি বেশ ভাল।

var wrench = require("wrench");

var files = wrench.readdirSyncRecursive("directory");

wrench.readdirRecursive("directory", function (error, files) {
    // live your dreams
});

সম্পাদনা (2018):
সাম্প্রতিক সময়ে যে কেউ পড়ছেন: লেখক ২০১৫ সালে এই প্যাকেজটি হ্রাস করেছেন:

wunch.js হ্রাস করা হয়েছে, এবং বেশ কিছু সময়ের মধ্যে আপডেট করা হয়নি। আমি অতিরিক্ত কোনও ফাইল সিস্টেমের ক্রিয়াকলাপ করতে ভারীভাবে এফএস-অতিরিক্ত ব্যবহারের পরামর্শ দিচ্ছি


@ ডমনিক, আপনি কীভাবে denodifyএটি করেন? কলব্যাক একাধিকবার (পুনরাবৃত্তভাবে) নিক্ষেপ করা হয়। সুতরাং Q.denodify(wrench.readdirRecursive)রিটার্ন ব্যবহার করে কেবল প্রথম ফলাফল।
ওনুর ইল্ডারিয়াম

1
@ অনুরাইল্ডারম হ্যাঁ, প্রতিশ্রুতি যেমন ঠিক তেমন উপযুক্ত নয়। আপনাকে এমন কিছু লিখতে হবে যা একাধিক প্রতিশ্রুতি দেয়, বা এমন কোনও কিছু যা প্রতিশ্রুতি ফেরানোর আগে সমস্ত সাবডিয়ারদের গণনা না করা পর্যন্ত অপেক্ষা করে। পরবর্তীকালের জন্য, github.com/kriskowal/q-io#listdirectorytreepath দেখুন
ডোমেনিক

9

আমি উপরের chjj থেকে উত্তরটি পছন্দ করেছি এবং এটি শুরু না করে প্যারালাল লুপটির আমার সংস্করণ তৈরি করতে সক্ষম হত না।

var fs = require("fs");

var tree = function(dir, done) {
  var results = {
        "path": dir
        ,"children": []
      };
  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) {
      fs.stat(dir + '/' + file, function(err, stat) {
        if (stat && stat.isDirectory()) {
          tree(dir + '/' + file, function(err, res) {
            results.children.push(res);
            if (!--pending){ done(null, results); }
          });
        } else {
          results.children.push({"path": dir + "/" + file});
          if (!--pending) { done(null, results); }
        }
      });
    });
  });
};

module.exports = tree;

আমি একটি গিস্টও তৈরি করেছি। মন্তব্য স্বাগত। আমি এখনও নোডজেএস রাজ্যে শুরু করছি যাতে এটি আরও একটি উপায় আশা করি।


8

আপনার পছন্দসই আউটপুট উত্পাদন করতে নোড-ডির ব্যবহার করুন

var dir = require('node-dir');

dir.files(__dirname, function(err, files) {
  if (err) throw err;
  console.log(files);
  //we have an array of files now, so now we can iterate that array
  files.forEach(function(path) {
    action(null, path);
  })
});

নোড-ডির ঠিকঠাক কাজ করছিল, কিন্তু যখন আমি ওয়েবপ্যাকটি দিয়ে এটি ব্যবহার করি তখন আমার কিছু অদ্ভুত সমস্যা রয়েছে। "যদি (ত্রুটি) in {" এর ফলে "অচিরত সিনট্যাক্স এরর: অপ্রত্যাশিত টোকেন error" ত্রুটি ঘটায় রিডফায়াল ফাংশনে একটি Â Âোকানো হয়। আমি এই ইস্যুতে স্তম্ভিত হয়েছি এবং আমার তাত্ক্ষণিক প্রতিক্রিয়া হ'ল নোড-দিরকে অনুরূপ কিছু দিয়ে প্রতিস্থাপন করা
পার্থ

1
@ পার্থ এই মন্তব্যটি আপনাকে উত্তর দেবে না। এসও তে একটি নতুন পূর্ণ প্রশ্ন লিখুন বা গিটহাব সংগ্রহস্থলে একটি সমস্যা তৈরি করুন। আপনি যখন আপনার প্রশ্নটি ভালভাবে বর্ণনা করেন, আপনি এমনকি পোস্ট না দিয়েই আপনার সমস্যার সমাধান করতে সক্ষম হতে পারেন
Christiaan Westerbeek

1
@ পার্থর মন্তব্য এখনও অন্যদের জন্য দরকারী সতর্কতা হতে পারে যারা আপনার পরামর্শটিকে তাদের সমস্যার সমাধান হিসাবে বিবেচনা করছেন। তারা এই মন্তব্য বিভাগে উত্তর খুঁজছেন না :) :)

8

পুনরাবৃত্তি সহ

var fs = require('fs')
var path = process.cwd()
var files = []

var getFiles = function(path, files){
    fs.readdirSync(path).forEach(function(file){
        var subpath = path + '/' + file;
        if(fs.lstatSync(subpath).isDirectory()){
            getFiles(subpath, files);
        } else {
            files.push(path + '/' + file);
        }
    });     
}

কল করা হচ্ছে

getFiles(path, files)
console.log(files) // will log all files in directory

3
আমি পথ স্ট্রিং যোগদান না করার সুপারিশ করছি /কিন্তু ব্যবহার pathমডিউল: path.join(searchPath, file)। এইভাবে, আপনি ওএসের থেকে পৃথক সঠিক পাথ পাবেন।
মরিৎজ ফ্রেডরিখ

4

আমি সম্প্রতি এটি কোডিং করেছি এবং ভেবেছি এটি এখানে ভাগ করে নেওয়া অর্থপূর্ণ হবে। কোডটি অ্যাসিঙ্ক লাইব্রেরিটি ব্যবহার করে ।

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

var scan = function(dir, suffix, callback) {
  fs.readdir(dir, function(err, files) {
    var returnFiles = [];
    async.each(files, function(file, next) {
      var filePath = dir + '/' + file;
      fs.stat(filePath, function(err, stat) {
        if (err) {
          return next(err);
        }
        if (stat.isDirectory()) {
          scan(filePath, suffix, function(err, results) {
            if (err) {
              return next(err);
            }
            returnFiles = returnFiles.concat(results);
            next();
          })
        }
        else if (stat.isFile()) {
          if (file.indexOf(suffix, file.length - suffix.length) !== -1) {
            returnFiles.push(filePath);
          }
          next();
        }
      });
    }, function(err) {
      callback(err, returnFiles);
    });
  });
};

আপনি এটি এর মতো ব্যবহার করতে পারেন:

scan('/some/dir', '.ext', function(err, files) {
  // Do something with files that ends in '.ext'.
  console.log(files);
});

2
এই. এটি এত পরিপাটি এবং সহজেই ব্যবহারযোগ্য। আমি এটি একটি মডিউলে পাম্প করেছিলাম, এটির প্রয়োজন এবং এটি এমসিড্রিম স্যান্ডউইচের মতো কাজ করে।
জয়

4

ফাইলহাউন্ড নামক একটি লাইব্রেরি অন্য বিকল্প। এটি পুনরাবৃত্তভাবে একটি প্রদত্ত ডিরেক্টরি অনুসন্ধান করবে (ডিফল্টরূপে ডিরেক্টরি ডিরেক্টরি)। এটি বিভিন্ন ফিল্টার, কলব্যাক, প্রতিশ্রুতি এবং সিঙ্ক অনুসন্ধানগুলিকে সমর্থন করে।

উদাহরণস্বরূপ, সমস্ত ফাইলের জন্য বর্তমান ওয়ার্কিং ডিরেক্টরিটি অনুসন্ধান করুন (কলব্যাক ব্যবহার করে):

const Filehound = require('filehound');

Filehound.create()
.find((err, files) => {
    if (err) {
        return console.error(`error: ${err}`);
    }
    console.log(files); // array of files
});

বা প্রতিশ্রুতিবদ্ধ এবং একটি নির্দিষ্ট ডিরেক্টরি নির্দিষ্ট করে:

const Filehound = require('filehound');

Filehound.create()
.paths("/tmp")
.find()
.each(console.log);

আরও ব্যবহারের ক্ষেত্রে এবং ব্যবহারের উদাহরণগুলির জন্য ডক্সের সাথে পরামর্শ করুন: https://github.com/nspragg/filehound

দাবি অস্বীকার: আমি লেখক।


4

অ্যাসিঙ্ক / প্রতীক্ষা ব্যবহার করে এটি কাজ করা উচিত:

const FS = require('fs');
const readDir = promisify(FS.readdir);
const fileStat = promisify(FS.stat);

async function getFiles(dir) {
    let files = await readDir(dir);

    let result = files.map(file => {
        let path = Path.join(dir,file);
        return fileStat(path).then(stat => stat.isDirectory() ? getFiles(path) : path);
    });

    return flatten(await Promise.all(result));
}

function flatten(arr) {
    return Array.prototype.concat(...arr);
}

আপনি ব্যবহার করতে পারেন bluebird.Promisify বা এই:

/**
 * Returns a function that will wrap the given `nodeFunction`. Instead of taking a callback, the returned function will return a promise whose fate is decided by the callback behavior of the given node function. The node function should conform to node.js convention of accepting a callback as last argument and calling that callback with error as the first argument and success value on the second argument.
 *
 * @param {Function} nodeFunction
 * @returns {Function}
 */
module.exports = function promisify(nodeFunction) {
    return function(...args) {
        return new Promise((resolve, reject) => {
            nodeFunction.call(this, ...args, (err, data) => {
                if(err) {
                    reject(err);
                } else {
                    resolve(data);
                }
            })
        });
    };
};

নোড 8+ এর অন্তর্নির্মিত প্রমিসিফাই রয়েছে

জেনারেটরের পদ্ধতির জন্য আমার অন্য উত্তরটি দেখুন যা আরও দ্রুত ফলাফল দিতে পারে।


4

এসিঙ্ক

const fs = require('fs')
const path = require('path')

const readdir = (p, done, a = [], i = 0) => fs.readdir(p, (e, d = []) =>
  d.map(f => readdir(a[a.push(path.join(p, f)) - 1], () =>
    ++i == d.length && done(a), a)).length || done(a))

readdir(__dirname, console.log)

সুসংগত

const fs = require('fs')
const path = require('path')

const readdirSync = (p, a = []) => {
  if (fs.statSync(p).isDirectory())
    fs.readdirSync(p).map(f => readdirSync(a[a.push(path.join(p, f)) - 1], a))
  return a
}

console.log(readdirSync(__dirname))

অ্যাসিঙ্ক পঠনযোগ্য

function readdir (currentPath, done, allFiles = [], i = 0) {
  fs.readdir(currentPath, function (e, directoryFiles = []) {
    if (!directoryFiles.length)
      return done(allFiles)
    directoryFiles.map(function (file) {
      var joinedPath = path.join(currentPath, file)
      allFiles.push(joinedPath)
      readdir(joinedPath, function () {
        i = i + 1
        if (i == directoryFiles.length)
          done(allFiles)}
      , allFiles)
    })
  })
}

readdir(__dirname, console.log)

দ্রষ্টব্য: উভয় সংস্করণ symlinks অনুসরণ করবে (মূল হিসাবে একই fs.readdir)



2

একক প্রতিশ্রুতি বাস্তবায়ন

আমি এই উদাহরণে কখন . js প্রতিশ্রুতি পাঠাগার ব্যবহার করছি ।

var fs = require('fs')
, path = require('path')
, when = require('when')
, nodefn = require('when/node/function');

function walk (directory, includeDir) {
    var results = [];
    return when.map(nodefn.call(fs.readdir, directory), function(file) {
        file = path.join(directory, file);
        return nodefn.call(fs.stat, file).then(function(stat) {
            if (stat.isFile()) { return results.push(file); }
            if (includeDir) { results.push(file + path.sep); }
            return walk(file, includeDir).then(function(filesInDir) {
                results = results.concat(filesInDir);
            });
        });
    }).then(function() {
        return results;
    });
};

walk(__dirname).then(function(files) {
    console.log(files);
}).otherwise(function(error) {
    console.error(error.stack || error);
});

আমি একটি alচ্ছিক প্যারামিটার অন্তর্ভুক্ত করেছি includeDirযা সেট করা থাকলে ফাইল তালিকাতে ডিরেক্টরি অন্তর্ভুক্ত করা হবে true



1

এখানে আরও একটি বাস্তবায়ন রয়েছে। উপরের সমাধানগুলির কোনওটিরই কোনও সীমাবদ্ধতা নেই, এবং তাই যদি আপনার ডিরেক্টরি কাঠামো বড় হয় তবে সেগুলি সমস্ত ছিটকে যাবে এবং শেষ পর্যন্ত সংস্থান থেকে বেরিয়ে আসবে।

var async = require('async');
var fs = require('fs');
var resolve = require('path').resolve;

var scan = function(path, concurrency, callback) {
    var list = [];

    var walker = async.queue(function(path, callback) {
        fs.stat(path, function(err, stats) {
            if (err) {
                return callback(err);
            } else {
                if (stats.isDirectory()) {
                    fs.readdir(path, function(err, files) {
                        if (err) {
                            callback(err);
                        } else {
                            for (var i = 0; i < files.length; i++) {
                                walker.push(resolve(path, files[i]));
                            }
                            callback();
                        }
                    });
                } else {
                    list.push(path);
                    callback();
                }
            }
        });
    }, concurrency);

    walker.push(path);

    walker.drain = function() {
        callback(list);
    }
};

50 এর একচ্ছত্র ব্যবহারটি বেশ ভাল কাজ করে এবং ছোট ডিরেক্টরি স্ট্রাকচারের জন্য প্রায়শই সহজ বাস্তবায়ন হিসাবে তত দ্রুত।



1

আমি ব্লুবার্ডের সাথে কাজ করার জন্য ট্রেভর সিনিয়রদের প্রতিশ্রুতি ভিত্তিক উত্তরটি সংশোধন করেছি

var fs = require('fs'),
    path = require('path'),
    Promise = require('bluebird');

var readdirAsync = Promise.promisify(fs.readdir);
var statAsync = Promise.promisify(fs.stat);
function walkFiles (directory) {
    var results = [];
    return readdirAsync(directory).map(function(file) {
        file = path.join(directory, file);
        return statAsync(file).then(function(stat) {
            if (stat.isFile()) {
                return results.push(file);
            }
            return walkFiles(file).then(function(filesInDir) {
                results = results.concat(filesInDir);
            });
        });
    }).then(function() {
        return results;
    });
}

//use
walkDir(__dirname).then(function(files) {
    console.log(files);
}).catch(function(e) {
    console.error(e); {
});

1

মজাদার জন্য, এখানে একটি প্রবাহ ভিত্তিক সংস্করণ যা পার্বত্যাঞ্চলীয়.কম স্ট্রিম লাইব্রেরির সাথে কাজ করে। এটি সহ-লেখক ছিলেন ভিক্টর ভু।

###
  directory >---m------> dirFilesStream >---------o----> out
                |                                 |
                |                                 |
                +--------< returnPipe <-----------+

  legend: (m)erge  (o)bserve

 + directory         has the initial file
 + dirListStream     does a directory listing
 + out               prints out the full path of the file
 + returnPipe        runs stat and filters on directories

###

_ = require('highland')
fs = require('fs')
fsPath = require('path')

directory = _(['someDirectory'])
mergePoint = _()
dirFilesStream = mergePoint.merge().flatMap((parentPath) ->
  _.wrapCallback(fs.readdir)(parentPath).sequence().map (path) ->
    fsPath.join parentPath, path
)
out = dirFilesStream
# Create the return pipe
returnPipe = dirFilesStream.observe().flatFilter((path) ->
  _.wrapCallback(fs.stat)(path).map (v) ->
    v.isDirectory()
)
# Connect up the merge point now that we have all of our streams.
mergePoint.write directory
mergePoint.write returnPipe
mergePoint.end()
# Release backpressure.  This will print files as they are discovered
out.each H.log
# Another way would be to queue them all up and then print them all out at once.
# out.toArray((files)-> console.log(files))

1

এটি কার্যকরী শৈলীতে সমাধান করার জন্য প্রতিশ্রুতি ( প্রশ্ন ) ব্যবহার করে :

var fs = require('fs'),
    fsPath = require('path'),
    Q = require('q');

var walk = function (dir) {
  return Q.ninvoke(fs, 'readdir', dir).then(function (files) {

    return Q.all(files.map(function (file) {

      file = fsPath.join(dir, file);
      return Q.ninvoke(fs, 'lstat', file).then(function (stat) {

        if (stat.isDirectory()) {
          return walk(file);
        } else {
          return [file];
        }
      });
    }));
  }).then(function (files) {
    return files.reduce(function (pre, cur) {
      return pre.concat(cur);
    });
  });
};

এটি কোনও অ্যারের প্রতিশ্রুতি দেয়, যাতে আপনি এটি ব্যবহার করতে পারেন:

walk('/home/mypath').then(function (files) { console.log(files); });

1

আমাকে অবশ্যই প্রতিশ্রুতি ভিত্তিক স্যান্ডার লাইব্রেরিটি তালিকায় যুক্ত করতে হবে।

 var sander = require('sander');
 sander.lsr(directory).then( filenames => { console.log(filenames) } );

1

ব্লুবার্ড প্রতিশ্রুতি ব্যবহার করুন।

let promise = require('bluebird'),
    PC = promise.coroutine,
    fs = promise.promisifyAll(require('fs'));
let getFiles = PC(function*(dir){
    let files = [];
    let contents = yield fs.readdirAsync(dir);
    for (let i = 0, l = contents.length; i < l; i ++) {
        //to remove dot(hidden) files on MAC
        if (/^\..*/.test(contents[i])) contents.splice(i, 1);
    }
    for (let i = 0, l = contents.length; i < l; i ++) {
        let content = path.resolve(dir, contents[i]);
        let contentStat = yield fs.statAsync(content);
        if (contentStat && contentStat.isDirectory()) {
            let subFiles = yield getFiles(content);
            files = files.concat(subFiles);
        } else {
            files.push(content);
        }
    }
    return files;
});
//how to use
//easy error handling in one place
getFiles(your_dir).then(console.log).catch(err => console.log(err));

0

কারণ প্রত্যেকের নিজের লেখা উচিত, আমি একটি তৈরি করেছিলাম।

ওয়াক (দির, সিবি, এন্ডসিবি) সিবি (ফাইল) এন্ডসিবি (এরর | নাল)

ময়লা

module.exports = walk;

function walk(dir, cb, endCb) {
  var fs = require('fs');
  var path = require('path');

  fs.readdir(dir, function(err, files) {
    if (err) {
      return endCb(err);
    }

    var pending = files.length;
    if (pending === 0) {
      endCb(null);
    }
    files.forEach(function(file) {
      fs.stat(path.join(dir, file), function(err, stats) {
        if (err) {
          return endCb(err)
        }

        if (stats.isDirectory()) {
          walk(path.join(dir, file), cb, function() {
            pending--;
            if (pending === 0) {
              endCb(null);
            }
          });
        } else {
          cb(path.join(dir, file));
          pending--;
          if (pending === 0) {
            endCb(null);
          }
        }
      })
    });

  });
}

0

লোডডির https://npmjs.org/package/loaddir দেখুন

npm install loaddir

  loaddir = require('loaddir')

  allJavascripts = []
  loaddir({
    path: __dirname + '/public/javascripts',
    callback: function(){  allJavascripts.push(this.relativePath + this.baseName); }
  })

আপনার যদি এক্সটেনশানটির প্রয়োজন হয় তবে তার fileNameপরিবর্তে আপনি ব্যবহার করতে পারেন baseName

একটি যুক্ত বোনাস হ'ল এটি ফাইলগুলিও দেখতে পাবে এবং আবার কলব্যাক কল করবে। এটিকে অত্যন্ত নমনীয় করে তোলার জন্য প্রচুর কনফিগারেশন বিকল্প রয়েছে।

আমি মাত্র guardকিছুক্ষণের মধ্যে লোডডির ব্যবহার করে রুবি থেকে মণির পুনর্নির্মাণ করেছি


0

এই আমার উত্তর। আশা করি এটি কারও সাহায্য করতে পারে।

আমার ফোকাসটি অনুসন্ধানের রুটিনটি যে কোনও জায়গায় থামতে পারে তা করা এবং একটি ফাইলের জন্য, আপেক্ষিক গভীরতাটিকে মূল পথটিকে বলে।

var _fs = require('fs');
var _path = require('path');
var _defer = process.nextTick;

// next() will pop the first element from an array and return it, together with
// the recursive depth and the container array of the element. i.e. If the first
// element is an array, it'll be dug into recursively. But if the first element is
// an empty array, it'll be simply popped and ignored.
// e.g. If the original array is [1,[2],3], next() will return [1,0,[[2],3]], and
// the array becomes [[2],3]. If the array is [[[],[1,2],3],4], next() will return
// [1,2,[2]], and the array becomes [[[2],3],4].
// There is an infinity loop `while(true) {...}`, because I optimized the code to
// make it a non-recursive version.
var next = function(c) {
    var a = c;
    var n = 0;
    while (true) {
        if (a.length == 0) return null;
        var x = a[0];
        if (x.constructor == Array) {
            if (x.length > 0) {
                a = x;
                ++n;
            } else {
                a.shift();
                a = c;
                n = 0;
            }
        } else {
            a.shift();
            return [x, n, a];
        }
    }
}

// cb is the callback function, it have four arguments:
//    1) an error object if any exception happens;
//    2) a path name, may be a directory or a file;
//    3) a flag, `true` means directory, and `false` means file;
//    4) a zero-based number indicates the depth relative to the original path.
// cb should return a state value to tell whether the searching routine should
// continue: `true` means it should continue; `false` means it should stop here;
// but for a directory, there is a third state `null`, means it should do not
// dig into the directory and continue searching the next file.
var ls = function(path, cb) {
    // use `_path.resolve()` to correctly handle '.' and '..'.
    var c = [ _path.resolve(path) ];
    var f = function() {
        var p = next(c);
        p && s(p);
    };
    var s = function(p) {
        _fs.stat(p[0], function(err, ss) {
            if (err) {
                // use `_defer()` to turn a recursive call into a non-recursive call.
                cb(err, p[0], null, p[1]) && _defer(f);
            } else if (ss.isDirectory()) {
                var y = cb(null, p[0], true, p[1]);
                if (y) r(p);
                else if (y == null) _defer(f);
            } else {
                cb(null, p[0], false, p[1]) && _defer(f);
            }
        });
    };
    var r = function(p) {
        _fs.readdir(p[0], function(err, files) {
            if (err) {
                cb(err, p[0], true, p[1]) && _defer(f);
            } else {
                // not use `Array.prototype.map()` because we can make each change on site.
                for (var i = 0; i < files.length; i++) {
                    files[i] = _path.join(p[0], files[i]);
                }
                p[2].unshift(files);
                _defer(f);
            }
        });
    }
    _defer(f);
};

var printfile = function(err, file, isdir, n) {
    if (err) {
        console.log('-->   ' + ('[' + n + '] ') + file + ': ' + err);
        return true;
    } else {
        console.log('... ' + ('[' + n + '] ') + (isdir ? 'D' : 'F') + ' ' + file);
        return true;
    }
};

var path = process.argv[2];
ls(path, printfile);

0

এখানে সাব-ডাইরেক্টরিগুলি সহ সমস্ত ফাইল পাওয়ার একটি পুনরাবৃত্ত পদ্ধতি।

const FileSystem = require("fs");
const Path = require("path");

//...

function getFiles(directory) {
    directory = Path.normalize(directory);
    let files = FileSystem.readdirSync(directory).map((file) => directory + Path.sep + file);

    files.forEach((file, index) => {
        if (FileSystem.statSync(file).isDirectory()) {
            Array.prototype.splice.apply(files, [index, 1].concat(getFiles(file)));
        }
    });

    return files;
}

0

আরেকটি সহজ এবং সহায়ক

function walkDir(root) {
    const stat = fs.statSync(root);

    if (stat.isDirectory()) {
        const dirs = fs.readdirSync(root).filter(item => !item.startsWith('.'));
        let results = dirs.map(sub => walkDir(`${root}/${sub}`));
        return [].concat(...results);
    } else {
        return root;
    }
}

আপনি ধরে নিচ্ছেন যে মূল ডিরেক্টরিতে প্রতিটি ফাইলই এখানে একটি ফোল্ডার।
xechelonx

0

পুনরাবৃত্তভাবে একটি ডিরেক্টরি অনুসন্ধান করতে আমি এইভাবে নোডেজ fs.readdir ফাংশনটি ব্যবহার করি।

const fs = require('fs');
const mime = require('mime-types');
const readdirRecursivePromise = path => {
    return new Promise((resolve, reject) => {
        fs.readdir(path, (err, directoriesPaths) => {
            if (err) {
                reject(err);
            } else {
                if (directoriesPaths.indexOf('.DS_Store') != -1) {
                    directoriesPaths.splice(directoriesPaths.indexOf('.DS_Store'), 1);
                }
                directoriesPaths.forEach((e, i) => {
                    directoriesPaths[i] = statPromise(`${path}/${e}`);
                });
                Promise.all(directoriesPaths).then(out => {
                    resolve(out);
                }).catch(err => {
                    reject(err);
                });
            }
        });
    });
};
const statPromise = path => {
    return new Promise((resolve, reject) => {
        fs.stat(path, (err, stats) => {
            if (err) {
                reject(err);
            } else {
                if (stats.isDirectory()) {
                    readdirRecursivePromise(path).then(out => {
                        resolve(out);
                    }).catch(err => {
                        reject(err);
                    });
                } else if (stats.isFile()) {
                    resolve({
                        'path': path,
                        'type': mime.lookup(path)
                    });
                } else {
                    reject(`Error parsing path: ${path}`);
                }
            }
        });
    });
};
const flatten = (arr, result = []) => {
    for (let i = 0, length = arr.length; i < length; i++) {
        const value = arr[i];
        if (Array.isArray(value)) {
            flatten(value, result);
        } else {
            result.push(value);
        }
    }
    return result;
};

ধরা যাক আপনার নোড প্রকল্পের মূলটিতে '/ ডাটাবেস' নামে একটি পথ রয়েছে। এই প্রতিশ্রুতিটি সমাধান হয়ে গেলে, এটি '/ ডাটাবেস' এর অধীনে প্রতিটি ফাইলের একটি অ্যারের ছুঁড়ে ফেলা উচিত।

readdirRecursivePromise('database').then(out => {
    console.log(flatten(out));
}).catch(err => {
    console.log(err);
});
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.