দ্রুততম উপায় হ'ল একটি উদ্দেশ্য-নির্মিত প্রোগ্রাম, এর মতো:
#include <stdio.h>
#include <dirent.h>
int main(int argc, char *argv[]) {
DIR *dir;
struct dirent *ent;
long count = 0;
dir = opendir(argv[1]);
while((ent = readdir(dir)))
++count;
closedir(dir);
printf("%s contains %ld files\n", argv[1], count);
return 0;
}
ক্যাশে বিবেচনা না করে আমার পরীক্ষা করা থেকে, ক্যাশে-ভিত্তিক ডেটা স্কিউ এড়াতে আমি প্রায় প্রতিটি বার একই ডিরেক্টরিটির বিরুদ্ধে প্রায় 50 বার দৌড়েছি এবং মোটামুটি নিম্নলিখিত কর্মক্ষমতা নম্বর পেয়েছি (আসল ঘড়ির সময়):
ls -1 | wc - 0:01.67
ls -f1 | wc - 0:00.14
find | wc - 0:00.22
dircnt | wc - 0:00.04
এটি শেষটি,, dircnt
উপরোক্ত উত্স থেকে সংকলিত প্রোগ্রাম।
সম্পাদনা 2016-09-26
জনপ্রিয় চাহিদার কারণে, আমি পুনরায় লিখেছি এই প্রোগ্রামটি পুনরাবৃত্ত হওয়ার জন্য, তাই এটি উপ-ডিরেক্টরিতে নেমে আসবে এবং পৃথকভাবে ফাইল এবং ডিরেক্টরি গণনাতে থাকবে।
যেহেতু এটি স্পষ্ট হয়েছে যে কিছু লোকেরা কীভাবে এটি করতে হয় তা জানতে চায় , তাই কী চলছে তা সুস্পষ্ট করার চেষ্টা করার জন্য কোডটিতে আমার অনেক মন্তব্য রয়েছে। আমি এটি লিখেছি এবং এটি 64৪-বিট লিনাক্সে পরীক্ষা করেছি, তবে এটি মাইক্রোসফ্ট উইন্ডোজ সহ কোনও পসিক্স-কমপ্লায়েন্ট সিস্টেমে কাজ করা উচিত । বাগ রিপোর্ট স্বাগত; আপনি যদি এটি আপনার এআইএক্স বা ওএস / 400 বা যে কোনও কিছুতে কাজ করতে না পান তবে আমি এটি আপডেট করে খুশি।
আপনি দেখতে পাচ্ছেন, এটি আসলটির চেয়ে অনেক জটিল এবং অগত্যা প্রয়োজনীয়: আপনি কোডটি খুব জটিল হয়ে উঠতে না চাইলে অবশ্যই কমপক্ষে একটি ফাংশন অবশ্যই পুনরুক্তি বলা যেতে পারে (যেমন একটি সাব-ডিরেক্টরী স্ট্যাক পরিচালনা করা এবং এটি একটি একক লুপে প্রক্রিয়াকরণ)। যেহেতু আমাদের ফাইলের প্রকারগুলি পরীক্ষা করতে হবে, বিভিন্ন ওএস, স্ট্যান্ডার্ড লাইব্রেরি ইত্যাদির মধ্যে পার্থক্য খেলতে আসে, তাই আমি একটি প্রোগ্রাম লিখেছি যেখানে এটি সংকলিত হবে এমন কোনও সিস্টেমে ব্যবহারের যোগ্য হওয়ার চেষ্টা করে।
খুব কম ত্রুটি পরীক্ষা করা আছে, এবং count
ফাংশনটি নিজেই সত্যই ত্রুটির প্রতিবেদন করে না। কেবলমাত্র কলগুলি যা সত্যই ব্যর্থ হতে পারে সেগুলি হ'ল opendir
এবং stat
(যদি আপনি ভাগ্যবান না হন এবং dirent
ইতিমধ্যে ফাইল টাইপ রয়েছে এমন কোনও সিস্টেম থাকে)। আমি সাবডির প্যাথনামগুলির মোট দৈর্ঘ্য পরীক্ষা করার বিষয়ে ভৌগলিক নই, তবে তাত্ত্বিকভাবে, সিস্টেমটির চেয়ে কোনও দীর্ঘ পথের নামটির অনুমতি দেওয়া উচিত নয় PATH_MAX
। যদি উদ্বেগ থাকে তবে আমি এটি সংশোধন করতে পারি, তবে এটি কেবলমাত্র আরও কোড যা সি লিখতে শেখা কাউকে ব্যাখ্যা করা দরকার এই প্রোগ্রামটি কীভাবে পুনরাবৃত্তির সাথে সাব-ডিরেক্টরিতে ডুব দেওয়া যায় তার উদাহরণ হতে পারে to
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/stat.h>
#if defined(WIN32) || defined(_WIN32)
#define PATH_SEPARATOR '\\'
#else
#define PATH_SEPARATOR '/'
#endif
/* A custom structure to hold separate file and directory counts */
struct filecount {
long dirs;
long files;
};
/*
* counts the number of files and directories in the specified directory.
*
* path - relative pathname of a directory whose files should be counted
* counts - pointer to struct containing file/dir counts
*/
void count(char *path, struct filecount *counts) {
DIR *dir; /* dir structure we are reading */
struct dirent *ent; /* directory entry currently being processed */
char subpath[PATH_MAX]; /* buffer for building complete subdir and file names */
/* Some systems don't have dirent.d_type field; we'll have to use stat() instead */
#if !defined ( _DIRENT_HAVE_D_TYPE )
struct stat statbuf; /* buffer for stat() info */
#endif
/* fprintf(stderr, "Opening dir %s\n", path); */
dir = opendir(path);
/* opendir failed... file likely doesn't exist or isn't a directory */
if(NULL == dir) {
perror(path);
return;
}
while((ent = readdir(dir))) {
if (strlen(path) + 1 + strlen(ent->d_name) > PATH_MAX) {
fprintf(stdout, "path too long (%ld) %s%c%s", (strlen(path) + 1 + strlen(ent->d_name)), path, PATH_SEPARATOR, ent->d_name);
return;
}
/* Use dirent.d_type if present, otherwise use stat() */
#if defined ( _DIRENT_HAVE_D_TYPE )
/* fprintf(stderr, "Using dirent.d_type\n"); */
if(DT_DIR == ent->d_type) {
#else
/* fprintf(stderr, "Don't have dirent.d_type, falling back to using stat()\n"); */
sprintf(subpath, "%s%c%s", path, PATH_SEPARATOR, ent->d_name);
if(lstat(subpath, &statbuf)) {
perror(subpath);
return;
}
if(S_ISDIR(statbuf.st_mode)) {
#endif
/* Skip "." and ".." directory entries... they are not "real" directories */
if(0 == strcmp("..", ent->d_name) || 0 == strcmp(".", ent->d_name)) {
/* fprintf(stderr, "This is %s, skipping\n", ent->d_name); */
} else {
sprintf(subpath, "%s%c%s", path, PATH_SEPARATOR, ent->d_name);
counts->dirs++;
count(subpath, counts);
}
} else {
counts->files++;
}
}
/* fprintf(stderr, "Closing dir %s\n", path); */
closedir(dir);
}
int main(int argc, char *argv[]) {
struct filecount counts;
counts.files = 0;
counts.dirs = 0;
count(argv[1], &counts);
/* If we found nothing, this is probably an error which has already been printed */
if(0 < counts.files || 0 < counts.dirs) {
printf("%s contains %ld files and %ld directories\n", argv[1], counts.files, counts.dirs);
}
return 0;
}
সম্পাদনা 2017-01-17
আমি @ ফ্লাইংকোডমোনকি দ্বারা প্রস্তাবিত দুটি পরিবর্তন সংযুক্ত করেছি:
lstat
পরিবর্তে ব্যবহার করুন stat
। আপনি যে ডিরেক্টরিটি স্ক্যান করছেন সেগুলিতে ডিরেক্টরিগুলি সংযুক্ত থাকলে এটি প্রোগ্রামটির আচরণ পরিবর্তন করবে change পূর্ববর্তী আচরণটি ছিল (সংযুক্ত) উপ-ডিরেক্টরিটি তার ফাইল গণনাটিকে সামগ্রিক গণনায় যুক্ত করবে; নতুন আচরণটি হ'ল লিঙ্কযুক্ত ডিরেক্টরিটি একটি একক ফাইল হিসাবে গণ্য হবে এবং এর সামগ্রীগুলি গণনা করা হবে না।
- যদি কোনও ফাইলের পথ খুব দীর্ঘ হয় তবে একটি ত্রুটি বার্তা প্রেরণ করা হবে এবং প্রোগ্রামটি থামবে।
সম্পাদনা 2017-06-29
যে কোনও ভাগ্যের সাথে, এটি এই উত্তরের শেষ সম্পাদনা হবে :)
কোডটি পেতে কিছুটা সহজ করার জন্য আমি এই কোডটি একটি গিটহাবের সংগ্রহস্থলে অনুলিপি করেছি (অনুলিপি / পেস্টের পরিবর্তে, আপনি কেবল উত্সটি ডাউনলোড করতে পারেন ), এবং এটি কারও পক্ষে একটি টান জমা দিয়ে কোনও সংশোধন প্রস্তাব দেওয়া সহজ করে তোলে -গিটহাব থেকে অনুরোধ।
উত্স অ্যাপাচি লাইসেন্স ২.০ এর আওতায় পাওয়া যায়। প্যাচগুলি * স্বাগতম!
- "প্যাচ" হ'ল আমার মতো পুরানো লোকেরা "পুল অনুরোধ" বলে।