Ls কমান্ড একটি বিশাল সংখ্যক ফাইল সহ ডিরেক্টরিতে কাজ করছে না


70

আমার একটি ডিরেক্টরি ছিল যার প্রায় 5 মিলিয়ন ফাইল ছিল। আমি যখন lsএই ডিরেক্টরিটির ভিতরে থেকে কমান্ডটি চালানোর চেষ্টা করেছি তখন আমার সিস্টেমটি প্রচুর পরিমাণে মেমরি গ্রাস করেছিল এবং এটি কিছুক্ষণ পরে স্তব্ধ হয়ে যায়। lsকমান্ডটি ব্যবহার না করে ফাইলগুলি তালিকাভুক্ত করার কোনও কার্যকর উপায় আছে কি ?


11
নিশ্চিত হয়ে নিন যে lsসেই ব্যবহারের জন্য আপনার কোনও উপাধ নেই --colorবা এর -Fঅর্থ lstat(2)প্রতিটি ফাইলের জন্য একটি করছেন doing
স্টাফেন চেজেলাস

4
যাইহোক, একক ডিরেক্টরিতে কয়েক মিলিয়ন ফাইল সঞ্চয় করা একটি খারাপ ধারণা। আপনি যদি ডিরেক্টরি বিন্যাসটি নিয়ন্ত্রণ করেন তবে সম্ভবত কিছু মানদণ্ডে এটি বিভক্ত করবেন?
d33tah

এটি কি খাঁটি lsকল ছিল বা আপনি বিকল্পগুলি ব্যবহার করেছেন?
হউক লেগেছে

1
@ d33tah হ্যাঁ, 5 মিলিয়ন অনেক! আমার রুট ফাইল সিস্টেমে million মিলিয়ন ইনোডের সীমা রয়েছে।
মাইকেল

7
আউটপুট থেকে 5 মিলিয়ন আইটেম - আপনি কীভাবে এটি দেখছেন - সাধারণ তালিকা দেখতে খুব বেশি - তাই আপনি কীসের জন্য তালিকা চান?
ব্যবহারকারী 151019

উত্তর:


66

ব্যবহার করে বাছাই এড়ানো:

ls --sort=none # "do not sort; list entries in directory order"

বা, সমতুল্য:

ls -U

10
আমি আশ্চর্য হয়েছি যে কলাম লেআউটটি কতটা ওভারহেড যুক্ত করে। -1পতাকা যোগ করা সাহায্য করতে পারে।
মাইকেল

সম্ভবত বেশি কিছু না, তবে প্রতিটি সামান্য কিছু সাহায্য করে, তাই না? :)
মাইকেল

1
@ মাইকেল এটি কি কেবল অনুমান, বা আপনি এটি পরিমাপ করেছেন? আমার কাছে মনে হয় এটি -1আরও বেশি সময় নেয়।
হউক লেগেইজ

10
"-1" বেশ কিছুটা সহায়তা করে। "ls -f -1" কোনও স্ট্যাট কল এড়াতে এবং সাথে সাথে সমস্ত কিছু মুদ্রণ করবে। কলাম আউটপুট (টার্মিনালে প্রেরণের সময় এটি ডিফল্ট) এটি প্রথমে সবকিছু বাফার করে। আমার সিস্টেমে, 8 মিলিয়ন ফাইলের সাথে একটি ডিরেক্টরিতে বিটিআরএফএস ব্যবহার করে ("সিক 1 1 8000000 | xargs টাচ" তৈরি করেছেন), "সময় ls -f -1 | wc -l" 5 সেকেন্ডের মধ্যে সময় নেয়, যখন "টাইম এলএস -f -C | wc -l "30 সেকেন্ডেরও বেশি সময় নেয়।
স্কট ল্যাম্ব

1
@ টলমেকারস্টেভ ডিফল্ট আচরণ ( -Cযখন স্টাডাউট একটি টার্মিনাল হয়, -1যখন এটি পাইপ হয়) বিভ্রান্ত হয়। আপনি যখন পরীক্ষা নিরীক্ষা করছেন এবং পরিমাপ করছেন, আপনি আউটপুটটি দেখেছিলেন (কমান্ডটি আপনার প্রত্যাশাটি কি করছে তা নিশ্চিত করার জন্য) এবং এটি দমন করতে (টার্মিনাল অ্যাপ্লিকেশনটির থ্রুপুটটির বিভ্রান্তিকর উপাদানটি এড়াতে) মধ্যে ফ্লিপ করুন। বেটার কমান্ড উভয় মোড মধ্যে একই ভাবে আচরণ ব্যবহার করতে, তাই স্পষ্টভাবে মাধ্যমে আউটপুট ফরম্যাট সংজ্ঞায়িত -1, -C, -l, ইত্যাদি
স্কট ভেড়ার

47

lsপ্রকৃতপক্ষে ফাইলগুলি বাছাই করে সেগুলি তালিকাভুক্ত করার চেষ্টা করে যা আমরা যদি কোনও ডিরেক্টরিতে এক মিলিয়নেরও বেশি ফাইল তালিকাভুক্ত করার চেষ্টা করি তবে এটি একটি বিশাল ওভারহেড হয়ে যায়। এই লিঙ্কে উল্লিখিত হিসাবে , আমরা ফাইলগুলি ব্যবহার করতে straceবা findতালিকা করতে পারি। যাইহোক, আমার কাছে 5 মিলিয়ন ফাইল থাকার কারণে এই বিকল্পগুলিও আমার সমস্যার কাছে অপরিহার্য বলে মনে হয়েছিল। Googling কিছু বিট পর, আমি দেখা গেছে যে যদি আমরা ব্যবহার ডিরেক্টরি তালিকা getdents(), এটি দ্রুত হবে, কারণ অনুমিত হয় ls, findএবং Pythonলাইব্রেরি ব্যবহার readdir()যা ধীর কিন্তু ব্যবহার getdents()নীচে।

আমরা এখানgetdents() থেকে ফাইলগুলি তালিকাবদ্ধ করতে সি কোড খুঁজে পেতে পারি :

/*
 * List directories using getdents() because ls, find and Python libraries
 * use readdir() which is slower (but uses getdents() underneath.
 *
 * Compile with 
 * ]$ gcc  getdents.c -o getdents
 */
#define _GNU_SOURCE
#include <dirent.h>     /* Defines DT_* constants */
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>

#define handle_error(msg) \
       do { perror(msg); exit(EXIT_FAILURE); } while (0)

struct linux_dirent {
   long           d_ino;
   off_t          d_off;
   unsigned short d_reclen;
   char           d_name[];
};

#define BUF_SIZE 1024*1024*5

int
main(int argc, char *argv[])
{
   int fd, nread;
   char buf[BUF_SIZE];
   struct linux_dirent *d;
   int bpos;
   char d_type;

   fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY);
   if (fd == -1)
       handle_error("open");

   for ( ; ; ) {
       nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
       if (nread == -1)
           handle_error("getdents");

       if (nread == 0)
           break;

       for (bpos = 0; bpos < nread;) {
           d = (struct linux_dirent *) (buf + bpos);
           d_type = *(buf + bpos + d->d_reclen - 1);
           if( d->d_ino != 0 && d_type == DT_REG ) {
              printf("%s\n", (char *)d->d_name );
           }
           bpos += d->d_reclen;
       }
   }

   exit(EXIT_SUCCESS);
}

উপরের সি প্রোগ্রামটিকে ডিরেক্টরিতে কপি করুন যেখানে ফাইলগুলি তালিকাবদ্ধ করা দরকার। তারপরে নীচের কমান্ডগুলি কার্যকর করুন।

gcc  getdents.c -o getdents
./getdents

সময় উদাহরণ : সিস্টেম কনফিগারেশন উপর নির্ভর করে getdentsতুলনায় অনেক দ্রুত হতে পারে ls -f। এখানে একটি সময় গণনা ক্লাস্টারে একটি এনএফএস মাউন্টে প্রায় 500k ফাইল ধারণকারী ডিরেক্টরি তালিকার জন্য 40x গতি বৃদ্ধি প্রদর্শন করছে। প্রতিটি কমান্ড অবিলম্বে পারম্পর্য মধ্যে 10 বার চালানো প্রথম, getdentsতারপর, ls -f। প্রথম রানটি অন্য সকলের তুলনায় উল্লেখযোগ্যভাবে ধীর, সম্ভবত এনএফএস ক্যাশিং পৃষ্ঠা ত্রুটির কারণে। (একদিকে: এই মাউন্টের উপরে, d_typeক্ষেত্রটি অবিশ্বাস্য, এই অর্থে যে অনেকগুলি ফাইল "অজানা" টাইপ হিসাবে উপস্থিত হয়))

command: getdents $bigdir
usr:0.08 sys:0.96  wall:280.79 CPU:0%
usr:0.06 sys:0.18  wall:0.25   CPU:97%
usr:0.05 sys:0.16  wall:0.21   CPU:99%
usr:0.04 sys:0.18  wall:0.23   CPU:98%
usr:0.05 sys:0.20  wall:0.26   CPU:99%
usr:0.04 sys:0.18  wall:0.22   CPU:99%
usr:0.04 sys:0.17  wall:0.22   CPU:99%
usr:0.04 sys:0.20  wall:0.25   CPU:99%
usr:0.06 sys:0.18  wall:0.25   CPU:98%
usr:0.06 sys:0.18  wall:0.25   CPU:98%
command: /bin/ls -f $bigdir
usr:0.53 sys:8.39  wall:8.97   CPU:99%
usr:0.53 sys:7.65  wall:8.20   CPU:99%
usr:0.44 sys:7.91  wall:8.36   CPU:99%
usr:0.50 sys:8.00  wall:8.51   CPU:100%
usr:0.41 sys:7.73  wall:8.15   CPU:99%
usr:0.47 sys:8.84  wall:9.32   CPU:99%
usr:0.57 sys:9.78  wall:10.36  CPU:99%
usr:0.53 sys:10.75 wall:11.29  CPU:99%
usr:0.46 sys:8.76  wall:9.25   CPU:99%
usr:0.50 sys:8.58  wall:9.13   CPU:99%

14
আপনি কি সময় অনুসারে একটি ছোট বেঞ্চমার্ক যুক্ত করতে পারবেন যার সাথে আপনার কেসটি প্রদর্শিত হবে ls?
বার্নহার্ড

1
মিষ্টি। এবং আপনি সহজেই এন্ট্রি (ফাইলগুলি) তাদের নাম তালিকাভুক্ত না করে (এই তালিকার জন্য প্রিন্টে কয়েক মিলিয়ন কল সংরক্ষণ করে) গণনা করার জন্য একটি বিকল্প যুক্ত করতে পারেন।
চককট্রিল

29
আপনি জানেন যে আপনার ডিরেক্টরিটি যখন এর বিষয়বস্তু তালিকাতে কাস্টম কোড লিখতে হয় তখন খুব বড় ...
কেসিসি

1
@ কেসি বাদে আপনার দরকার নেই। getdentsবনাম সম্পর্কে এই সমস্ত আলোচনা readdirবিন্দু মিস করে।
মাইকেল

9
চলে আসো! এটি ইতিমধ্যে সেখানে 5 মিলিয়ন ফাইল পেয়েছে। আপনার কাস্টম "ls" প্রোগ্রামটি অন্য কোনও ডিরেক্টরিতে রাখুন।
জোহান

12

এটি ধীর হওয়ার কারণ সম্ভবত ফাইল ফাইলের রঙ, আপনি এটিকে এড়ানো \lsবা /bin/lsরঙ বিকল্পগুলি বন্ধ করতে পারেন ।

আপনার যদি সত্যই অনেকগুলি ডিয়ারে থাকে তবে findপরিবর্তে ব্যবহার করাও একটি ভাল বিকল্প।


7
আমি মনে করি না এটি হ্রাস করা উচিত ছিল। বাছাই করা একটি সমস্যা, তবে এমনকি বাছাই ছাড়াই, প্রতিটি ফাইলই ls -U --colorঅনেক সময় নেয় stat। সুতরাং উভয় সঠিক।
মিকেল

কালারিং অফ করে দেওয়ার পারফরম্যান্সে বিশাল প্রভাব ফেলে lsএবং এটি ডিফল্টরূপে অনেকগুলি ক্ষেত্রেই আলাদা করা হয় .bashrc
ভিক্টর শ্রড্ডার

হ্যাঁ আমি একটি করেছি /bin/ls -Uএবং কোনও সময়ই আউটপুট পাইনি, এর আগে খুব দীর্ঘ সময়ের জন্য অপেক্ষা করার তুলনায়
খেব্বি

-3

আমি দেখতে পাচ্ছি যে echo *এলএস এর চেয়ে অনেক দ্রুত কাজ করে। YMMV।


4
শেলটি বাছাই করবে *। সুতরাং এই পদ্ধতিটি এখনও 5 মিলিয়ন ফাইলের জন্য খুব ধীর।
মিকেল

3
@ মাইকেল এর চেয়েও বেশি, আমি নিশ্চিত যে ৫ মিলিয়ন ফাইল এমন পর্যায়ে গেছে যেখানে গ্লোব্বিং পুরোপুরি ভেঙে যাবে।
কুরুচিহ্ন

4
ন্যূনতম ফাইলের নাম দৈর্ঘ্য (5 মিলিয়ন ফাইলের জন্য) 3 টি অক্ষর (সম্ভবত আপনি যদি আরও সাধারণ অক্ষরগুলিতে আঁকেন তবে 4) অতিরিক্ত প্রতিটি ডিলিমিটার = 4 অক্ষর প্রতি ফাইল, অর্থাৎ 20 এমবি কমান্ড আর্গুমেন্ট। এটি সাধারণ 2MB প্রসারিত কমান্ড লাইনের দৈর্ঘ্যের চেয়ে ভাল। এক্সেক (এবং এমনকি বিল্টিনগুলি) বাউল করত।
জোহান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.