ডিরেক্টরিতে কতগুলি ফাইল রয়েছে তা গণনা করার সর্বাধিক সংস্থান দক্ষ উপায় কী?


55

CentOS 5.9

আমি অন্য দিন একটি ইস্যু নিয়ে এসেছি যেখানে একটি ডিরেক্টরিতে প্রচুর ফাইল ছিল। এটি গণনা করতে, আমি দৌড়েls -l /foo/foo2/ | wc -l

দেখা যাচ্ছে যে একটি একক ডিরেক্টরিতে 1 মিলিয়ন ফাইল রয়েছে (দীর্ঘ গল্প - মূল কারণটি স্থির হয়ে উঠছে)।

আমার প্রশ্ন: গণনা করার কোনও দ্রুত উপায় আছে? গণনা পাওয়ার সবচেয়ে কার্যকর উপায় কী হবে?


5
ls -l|wc -lls -lআউটপুট প্রথম লাইনের মোট ব্লকগুলির কারণে এক এক হয়ে যাবে
টমাস নাইম্যান

3
@ থমাসনাইমেন ডট এবং ডটডট সিউডো এন্ট্রিগুলির কারণে এটি বেশ কয়েকটি দ্বারা বন্ধ হয়ে যাবে তবে -Aপতাকা ব্যবহার করে এগুলি এড়ানো সম্ভব । -lবর্ধিত তালিকার ফর্ম্যাটটি তৈরি করতে ফাইল মেটা ডেটা পড়ার কারণেও এটি সমস্যাযুক্ত। -lব্যবহার না করে বাধ্য \lsকরা একটি আরও ভাল বিকল্প ( -1আউটপুট পাইপ করার সময় ধরে নেওয়া হয়) এখানে সেরা সমাধানের জন্য গিলসের উত্তর দেখুন ।
কালেব

2
@Caleb ls -lনা আউটপুট কোন লুকানো ফাইল কিংবা করে .এবং ..এন্ট্রি। ls -aআউটপুট লুকানো ফাইল অন্তর্ভুক্ত সহ . এবং ..যখন ls -Aআউটপুট লুকানো ফাইল অন্তর্ভুক্ত ব্যতীত . এবং ..। ইন গিলেজ এর উত্তর ব্যাশ dotglob শেল বিকল্প লুকানো ফাইল অন্তর্ভুক্ত করা সম্প্রসারণ ঘটায় ব্যতীত . এবং ..
থমাস নাইম্যান

উত্তর:


61

সংক্ষিপ্ত উত্তর:

\ls -afq | wc -l

(এর মধ্যে রয়েছে .এবং ..তাই বিয়োগ 2)


আপনি যখন কোনও ডিরেক্টরিতে ফাইলগুলি তালিকাভুক্ত করেন, তখন তিনটি সাধারণ জিনিস ঘটতে পারে:

  1. ডিরেক্টরিতে ফাইলের নাম গণনা করা হচ্ছে। এটি অপরিবর্তনীয়: কোনও ডিরেক্টরিতে ফাইলগুলি গণনা না করে কোনও সংখ্যা গণনা করার উপায় নেই।
  2. ফাইলের নাম বাছাই করা হচ্ছে। শেল ওয়াইল্ডকার্ড এবং lsকমান্ড এটি করে।
  3. statপ্রতিটি ডিরেক্টরি এন্ট্রি সম্পর্কিত মেটাডেটা পুনরুদ্ধার করার জন্য কল করা, যেমন এটি ডিরেক্টরি কিনা।

# 3 এখন পর্যন্ত সবচেয়ে ব্যয়বহুল, কারণ এটি প্রতিটি ফাইলের জন্য একটি ইনোড লোড করা প্রয়োজন। তুলনায় তুলনা করে # 1 এর জন্য প্রয়োজনীয় সমস্ত ফাইলের ফাইলগুলি কয়েকটি ব্লকে নিখুঁতভাবে সংরক্ষণ করা হয়েছে। # 2 কিছু সিপিইউ সময় নষ্ট করে তবে এটি প্রায়শই ডিল ব্রেকার হয় না।

যদি ফাইলের নামগুলিতে কোনও নতুন লাইন না থাকে তবে একটি সরল ডিরেক্টরি ls -A | wc -lআপনাকে জানায় যে ডিরেক্টরিতে কতগুলি ফাইল রয়েছে। সাবধান হন যে আপনার যদি একটি উপাধি রয়েছে তবে এটি lsকলটি কল করতে পারে stat(উদাহরণস্বরূপ ls --colorবা ls -Fফাইলের প্রকারটি জানতে হবে, যার জন্য একটি কল প্রয়োজন stat), সুতরাং কমান্ড লাইন থেকে, কল করুন command ls -A | wc -lবা \ls -A | wc -lএকটি উপনাম এড়ানোর জন্য।

যদি ফাইলের নামে নতুন লাইন থাকে তবে নতুন লাইনগুলি তালিকাভুক্ত কিনা তা ইউনিক্স ভেরিয়েন্টের উপর নির্ভর করে। ?একটি নতুন লাইনের জন্য প্রদর্শিত GNU কোর্টিলস এবং ব্যাসিবক্স ডিফল্ট , যাতে তারা নিরাপদ থাকে।

ls -fএন্ট্রিগুলি বাছাই না করে তাদের তালিকা করতে কল করুন (# 2) এটি স্বয়ংক্রিয়ভাবে চালু হয় -a(কমপক্ষে আধুনিক সিস্টেমে)। -fবিকল্প POSIX কিন্তু ঐচ্ছিক অবস্থা সঙ্গে আছেন | বেশিরভাগ বাস্তবায়ন এটিকে সমর্থন করে তবে ব্যাসিবক্স নয়। বিকল্পটি -qমুদ্রণযোগ্য অক্ষরের পরিবর্তে নিউলাইনগুলি সহ প্রতিস্থাপন করে ?; এটি পসিক্স তবে ব্যাসিবক্স দ্বারা সমর্থিত নয়, সুতরাং আপনার যদি অতিরিক্ত ফাইলের ব্যয়ে ব্যাসিবক্স সমর্থন প্রয়োজন হয় তবে যার নামটিতে একটি নতুন লাইন অক্ষর রয়েছে it

যদি ডিরেক্টরিটির কোনও উপ-ডিরেক্টরি না থাকে, তবে বেশিরভাগ সংস্করণে তার এন্ট্রিগুলিতে findকল statকরা হবে না (লিফ ডিরেক্টরি ডিরেক্টরি অপ্টিমাইজেশন: ২ টির একটি লিঙ্ক গণনা রয়েছে এমন ডিরেক্টরিতে সাব-ডিরেক্টরি থাকতে পারে না, সুতরাং findএন্ট্রিগুলির মেটাডেটা সন্ধান করার প্রয়োজন নেই যদি না শর্ত যেমন -typeএটি প্রয়োজন)। সুতরাং find . | wc -lপোর্টেবল, দ্রুত প্রদান করা ডিরেক্টরিটি কোন সাবডিরেক্টরি এবং কোন ফাইলের নাম একটি newline রয়েছে সেটা একটি ডিরেক্টরির মধ্যে ফাইল গণনা উপায়।

ডিরেক্টরিতে যদি উপ-ডিরেক্টরি না থাকে তবে ফাইলের নামগুলিতে নতুন লাইন থাকতে পারে, এর মধ্যে একটি ব্যবহার করে দেখুন (দ্বিতীয়টি যদি এটি সমর্থন করে তবে দ্রুত হওয়া উচিত, তবে এটি সম্ভবত লক্ষ্যণীয় নয়)।

find -print0 | tr -dc \\0 | wc -c
find -printf a | wc -c

অন্যদিকে, findডিরেক্টরিটিতে সাব-ডিরেক্টরি থাকলেও ব্যবহার করবেন না : এমনকি প্রতিটি এন্ট্রিতেও find . -maxdepth 1কল statকরুন (কমপক্ষে জিএনইউ সন্ধান এবং ব্যাসিবক্স অনুসন্ধান সহ)। আপনি বাছাই এড়ান (# 2) তবে আপনি একটি ইনোড লুপ (# 3) এর মূল্য প্রদান করেন যা কার্য সম্পাদন করে।

বাহ্যিক সরঞ্জাম ছাড়া শেলটিতে আপনি বর্তমান ডিরেক্টরিতে ফাইলগুলি গণনা দিয়ে চালাতে পারেন set -- *; echo $#। এটি বিন্দু ফাইলগুলি (যাদের নাম দিয়ে শুরু হওয়া ফাইলগুলি .) মিস করে এবং খালি ডিরেক্টরিতে 0 এর পরিবর্তে 1 টি প্রতিবেদন করে। এটি ছোট ডিরেক্টরিতে ফাইলগুলি গণনা করার দ্রুততম উপায় কারণ এটিতে কোনও বাহ্যিক প্রোগ্রাম শুরু করার প্রয়োজন হয় না, তবে (zsh ব্যতীত) বাছাইকরণের ধাপের কারণে বৃহত্তর ডিরেক্টরিগুলির জন্য সময় নষ্ট হয় (# 2)।

  • ব্যাশে, এটি বর্তমান ডিরেক্টরিতে ফাইলগুলি গণনা করার একটি নির্ভরযোগ্য উপায়:

    shopt -s dotglob nullglob
    a=(*)
    echo ${#a[@]}
    
  • Ksh93 এ, বর্তমান ডিরেক্টরিতে ফাইলগুলি গণনা করার এটি একটি নির্ভরযোগ্য উপায়:

    FIGNORE='@(.|..)'
    a=(~(N)*)
    echo ${#a[@]}
    
  • Zsh এ, এটি বর্তমান ডিরেক্টরিতে ফাইলগুলি গণনা করার একটি নির্ভরযোগ্য উপায়:

    a=(*(DNoN))
    echo $#a
    

    আপনি যদি mark_dirsবিকল্প সেট, এটিকে বন্ধ করতে নিশ্চিত করুন: a=(*(DNoN^M))

  • যে কোনও পসিক্স শেল এ, বর্তমান ডিরেক্টরিতে ফাইলগুলি গণনা করার এটি একটি নির্ভরযোগ্য উপায়:

    total=0
    set -- *
    if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
    set -- .[!.]*
    if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
    set -- ..?*
    if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
    echo "$total"
    

এই সমস্ত পদ্ধতিতে zsh নাম বাদে ফাইলের নামগুলি বাছাই করা হয়।


1
> 1 মিলিয়ন ফাইলগুলিতে আমার পরীক্ষামূলক পরীক্ষাটি দেখায় যে আপনি যতক্ষণ পর্যন্ত আরও চেক করতে হবে এমন কোনও ঘোষণার মতো কিছু যোগ না করেন ততক্ষণ find -maxdepth 1সহজেই গতি রক্ষা করে । আপনি কি নিশ্চিত যে জিএনইউ আসলে কলগুলি খুঁজে পেয়েছে ? এমনকি মন্দাটি যদি আপনি এটিকে ফাইলের বিবরণ ফিরিয়ে দেয় তবে কতটা বগের তুলনা করা যায় না। অন্যদিকে স্পষ্ট গতি বিজয়ী ননসওয়ার্টিং গ্লোব ব্যবহার করছে। (বাছাই করা গ্লোবগুলি 2x ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে বেড়ে যায়। আমি ভাবছি যদি ফাইল সিস্টেমের ধরণগুলি এই ফলাফলগুলিকে উল্লেখযোগ্যভাবে প্রভাবিত করে। \ls -U-typestatfind -typels -lzshls
কালেব

@ কালেব আমি দৌড়ে গেলাম strace। এটি কেবলমাত্র সত্য যদি ডিরেক্টরিতে সাব-ডিরেক্টরি থাকে: অন্যথায় findলিফের ডিরেক্টরি অপ্টিমাইজেশন কিক ইন (এমনকি ছাড়াই -maxdepth 1), আমার এটি উল্লেখ করা উচিত ছিল। ফাইল সিস্টেমের ধরণ সহ অনেকগুলি ফলাফল ফলাফলকে প্রভাবিত করতে পারে ( statডাইরেক্টরিগুলি বৃক্ষ হিসাবে ডিরেক্টরী হিসাবে উপস্থাপনকারী ফাইলের তুলনায় লিনিয়ার তালিকার হিসাবে ডিরেক্টরি উপস্থাপনকারী ফাইল সিস্টেমে কল করা অনেক বেশি ব্যয়বহুল), ইনোডগুলি একসাথে তৈরি হয়েছিল এবং এইভাবে কাছাকাছি ছিল কিনা ডিস্কে, ঠান্ডা বা গরম ক্যাশে ইত্যাদিতে
গিলস 'অশুভ হওয়া বন্ধ করুন'

1
ঐতিহাসিকভাবে, ls -fকলিং প্রতিরোধ নির্ভরযোগ্য উপায় হয়েছে stat- এই প্রায়ই কেবল হিসাবে "আউটপুট সাজানো না" (যা এটি ঘটায়) আজ বর্ণনা করা হয়েছে আর জড়িত .এবং ..-Aএবং -Uমানক বিকল্প নয়।
র্যান্ডম 832

1
আপনি যদি বিশেষভাবে একটি সাধারণ এক্সটেনশন (বা অন্যান্য স্ট্রিং) দিয়ে ফাইল গণনা করতে চান, কমান্ডের মধ্যে এটি সন্নিবেশ করিয়ে অতিরিক্ত 2 অপসারণ করে নিন। এখানে একটি উদাহরণ রয়েছে:\ls -afq *[0-9].pdb | wc -l
স্টিভেন সি হাওল

version sh (AT&T Research) 93u+ 2012-08-01আমার দেবিয়ান -ভিত্তিক সিস্টেমে ksh93 সহ এফওয়াইআই FIGNOREকাজ করছে বলে মনে হয় না। .এবং ..এন্ট্রি ফলে অ্যারের মধ্যে অন্তর্ভুক্ত করা হয়
Sergiy Kolodyazhnyy

17
find /foo/foo2/ -maxdepth 1 | wc -l

আমার মেশিনে যথেষ্ট দ্রুত তবে স্থানীয় .ডিরেক্টরিটি গণনাতে যুক্ত হয়েছে।


1
ধন্যবাদ। আমি বোকা প্রশ্ন করতে বাধ্য যদিও: এটি দ্রুত কেন? কারণ এটি ফাইলের বৈশিষ্ট্যগুলি অনুসন্ধান করতে বিরক্ত করছে না?
মাইক বি

2
হ্যাঁ, এটা আমার বোঝাপড়া। যতক্ষণ আপনার -typeপ্যারামিটারটি ব্যবহার না findকরা তত দ্রুত হওয়া উচিতls
জোয়েল টেলর

1
হুঁ .... আমি যদি ভালভাবে ডকুমেন্টেশন বুঝতে পারি তবে এটি আমার উত্তরের চেয়ে ভাল হওয়া উচিত। আরও অভিজ্ঞতার সাথে যে কেউ যাচাই করতে পারবেন?
লুইস মাচুকা

-mindepth 1ডিরেক্টরি নিজেই বাদ দিতে একটি যুক্ত করুন ।
স্টাফেন চেজেলাস

8

ls -1Uপাইপটি কেবলমাত্র কিছুটা কম সম্পদ ব্যয় করার আগে ফাইল ফাইলগুলিকে বাছাই করার চেষ্টা করে না, এটি ডিস্কের ফোল্ডারে সাজানোর সাথে সাথে সেগুলি পড়ে। এছাড়া জন্য সামান্য কম কাজ মানে কম আউটপুট উৎপন্ন করে wc

আপনি ls -fকমপক্ষে শর্টকাট যা ব্যবহার করতে পারেন ls -1aU

পাইপ না করে কোনও কমান্ডের মাধ্যমে এটি করার কোনও সংস্থান-দক্ষ উপায় আছে কিনা আমি জানি না।


8
বিটিডব্লিউ, -1 জড়িত যখন আউটপুটটি পাইপে যায়
enzotib

@ এঞ্জোটিব - তাই না? বাহ ... প্রতিদিন নতুন কিছু শিখছে!
লুইস মাচুকা

6

তুলনার আরেকটি বিষয়। শেল অনেলাইনার না হয়েও এই সি প্রোগ্রামটি অতিরিক্ত কিছু করে না। নোট করুন যে আড়াল করা ফাইলগুলি আউটপুট মেলানোর জন্য উপেক্ষা করা হয় ls|wc -l( আউটপুট ls -l|wc -lপ্রথম লাইনের মোট ব্লকের কারণে এক দ্বারা বন্ধ থাকে)।

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <error.h>
#include <errno.h>

int main(int argc, char *argv[])
{
    int file_count = 0;
    DIR * dirp;
    struct dirent * entry;

    if (argc < 2)
        error(EXIT_FAILURE, 0, "missing argument");

    if(!(dirp = opendir(argv[1])))
        error(EXIT_FAILURE, errno, "could not open '%s'", argv[1]);

    while ((entry = readdir(dirp)) != NULL) {
        if (entry->d_name[0] == '.') { /* ignore hidden files */
            continue;
        }
        file_count++;
    }
    closedir(dirp);

    printf("%d\n", file_count);
}

readdir()Stdio এপিআই ব্যবহার করে কিছু ওভারহেড যুক্ত হয় এবং অন্তর্নিহিত সিস্টেম কলটিতে ( getdentsলিনাক্সে) পাস করা বাফারের আকারের উপর নিয়ন্ত্রণ দেয় না
স্টাফেন চ্যাজেলাস

3

আপনি চেষ্টা করতে পারেন perl -e 'opendir($dh,".");$i=0;while(readdir $dh){$i++};print "$i\n";'

আপনার শেল পাইপের সাথে সময়ের তুলনা করা আকর্ষণীয় হবে।


আমার পরীক্ষার তারিখে এই তিনটি দ্রুততম সমাধান (যেমন প্রায় কাছাকাছি ঠিক একই গতি রাখে find -maxdepth 1 | wc -l, \ls -AU | wc -lএবং zshভিত্তিক অ বাছাই উল্লিখিত glob এবং অ্যারে সংখ্যা)। অন্য কথায় এটি বহিরাগত ফাইলের বৈশিষ্ট্য বাছাই বা পড়ার মতো বিভিন্ন অদক্ষতার সাথে অপশনগুলিকে হারাতে পারে। আমি বলার উদ্যোগ নেব যেহেতু এটি আপনার কোনও উপার্জনও করে না, আপনি যদি ইতিমধ্যে পার্ল না হয়ে থাকেন তবে একটি সহজ সমাধান ব্যবহার করা ঠিক নয় :)
কালেব

নোট করুন যে এটিতে গণনাতে .এবং ..ডিরেক্টরি এন্ট্রি অন্তর্ভুক্ত থাকবে , সুতরাং আপনার ফাইলের প্রকৃত সংখ্যা (এবং উপ-ডিরেক্টরি) পেতে দুটি বিয়োগ করতে হবে। আধুনিক পার্লে, perl -E 'opendir $dh, "."; $i++ while readdir $dh; say $i - 2'এটি করবে।
ইলমারি করোনেন

2

এই উত্তর থেকে , আমি এটিকে একটি সম্ভাব্য সমাধান হিসাবে ভাবতে পারি।

/*
 * 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 | wc -l

1
কয়েকটি জিনিস: ১) আপনি যদি এর জন্য কোনও কাস্টম প্রোগ্রাম ব্যবহার করতে ইচ্ছুক হন তবে আপনি কেবল ফাইলগুলি গণনা করতে এবং গণনা মুদ্রণ করতে পারেন; 2) সাথে তুলনা করতে ls -f, মোটেও ফিল্টার করবেন না d_type, কেবলমাত্র d->d_ino != 0; 3) 2 বিয়োগ .এবং ..
মেটেই ডেভিড

একটি সময় উদাহরণস্বরূপ যেখানে এই 40x গৃহীত তুলনায় দ্রুততর জন্য লিঙ্ক উত্তর দেখার ls -f
মেটেই ডেভিড

1

কোনও বাশ-কেবল সমাধান, কোনও বাহ্যিক প্রোগ্রামের প্রয়োজন হয় না, তবে কতটা দক্ষ তা জানেন না:

list=(*)
echo "${#list[@]}"

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

@ কালেব, কেবলমাত্র ksh এর পুরানো সংস্করণগুলিতে এই ধরনের সীমা ছিল (এবং সেই বাক্য গঠন সমর্থন করে না) আফাইক AI অন্যান্য সমস্ত শেলগুলিতে, সীমাটি কেবল উপলব্ধ মেমরি। আপনি একটি পয়েন্ট পেয়েছেন যে এটি খুব অদক্ষ হতে চলেছে, বিশেষত বাশ।
স্টাফেন চেজেলাস

1

সম্ভবত সবচেয়ে রিসোর্স দক্ষ উপায় কোনও বাইরের প্রক্রিয়া আমন্ত্রণ জড়িত হবে। তাই আমি বাজি থাকতাম ...

cglb() ( c=0 ; set --
    tglb() { [ -e "$2" ] || [ -L "$2" ] &&
       c=$(($c+$#-1))
    }
    for glb in '.?*' \*
    do  tglb $1 ${glb##.*} ${glb#\*}
        set -- ..
    done
    echo $c
)

1
আপেক্ষিক নম্বর পেয়েছেন? কত ফাইলের জন্য?
স্মি

0

@ জোয়েলের উত্তর থেকে সমস্যাটি সমাধানের পরে, যেখানে এটি .ফাইল হিসাবে যুক্ত হয়েছে :

find /foo/foo2 -maxdepth 1 | tail -n +2 | wc -l

tailকেবল প্রথম লাইনটি সরিয়ে দেয়, এর অর্থ এটি .আর গণনা করা হয় না।


1
ইনপুটটির এক লাইন বাদ দেওয়ার জন্য পাইপের একটি জোড়া যুক্ত করা wcখুব কার্যকরী নয় কারণ ইনপুট আকারের ক্ষেত্রে ওভারহেড রৈখিকভাবে বৃদ্ধি পায় । এক্ষেত্রে, চূড়ান্ত গণনাটি কেবল একের দ্বারা বন্ধ হয়ে যাওয়ার জন্য ক্ষতিপূরণ দেওয়ার জন্য কেন হ্রাস করা হবে না, যা একটি ধ্রুবক সময় অপারেশন:echo $(( $(find /foo/foo2 -maxdepth 1 | wc -l) - 1))
টমাস নাইম্যান

1
অন্য কোনও প্রক্রিয়ার মাধ্যমে সেই পরিমাণ ডেটা ফিড করার পরিবর্তে, চূড়ান্ত আউটপুট সম্পর্কে কিছু গণিত করা সম্ভবত ভাল। let count = $(find /foo/foo2 -maxdepth 1 | wc -l) - 2
কালেব

0

পাইথনের os.listdir () আপনার জন্য কাজটি করতে পারে। এটি বিশেষ 'বাদে ডিরেক্টরিতে থাকা সামগ্রীর একটি অ্যারে দেয়।' এবং '..' ফাইলগুলি। এছাড়াও, নামে '\ n' এর মতো বিশেষ অক্ষরযুক্ত অ্যাবলেট ফাইলগুলি চিন্তা করার দরকার নেই।

python -c 'import os;print len(os.listdir("."))'

'ls -Af' কমান্ডের সাথে তুলনা করে উপরের পাইথন কমান্ডের দ্বারা নেওয়া সময় নীচে দেওয়া হয়েছে।

~ / পরীক্ষা $ সময় ls -Af | ডাব্লুসি-লি
399144

বাস্তব 0m0.300s
ব্যবহারকারী 0m0.104s
ss 0m0.240s
~ / পরীক্ষা $ সময় পাইথন -c 'আমদানি করুন; প্রিন্ট লেন (os.listdir ("।"))'
399142

আসল 0m0.249s
ব্যবহারকারী 0m0.064s
sys 0m0.180s

0

ls -1 | wc -lসঙ্গে সঙ্গে আমার মনে আসে। নিখুঁত একাডেমিকের ls -1Uচেয়ে দ্রুততর কিনা ls -1- পার্থক্যটি তুচ্ছ হওয়া উচিত তবে খুব বড় ডিরেক্টরিতে।


0

করতে সাবডিরেক্টরি অগ্রাহ্য গণনা থেকে, এখানে গিলেজ থেকে গৃহীত উত্তরে একটি পরিবর্তন আছে:

echo $(( $( \ls -afq target | wc -l ) - $( \ls -od target | cut -f2 -d' ') ))

বাহ্যিক $(( ))পাটিগণিত সম্প্রসারণ $( )প্রথম থেকে দ্বিতীয় সাবশেলের আউটপুট বিয়োগ করে $( )। প্রথমটি $( )হ'ল উপর থেকে ঠিক গিলস '। দ্বিতীয়টি $( )ডিরেক্টরিকে "লিঙ্কিং" এর গণনা আউটপুট করে। এটি আসে ls -od(বিকল্প ls -ldযদি প্রয়োজন হয়), যেখানে কলামে হার্ড লিঙ্কগুলির গণনা তালিকাভুক্ত করে তা ডিরেক্টরিগুলির একটি বিশেষ অর্থ হিসাবে রয়েছে। "লিঙ্ক" সংখ্যা অন্তর্ভুক্ত করে ., ..এবং যে কোনো সাব।

আমি পারফরম্যান্স পরীক্ষা করিনি, তবে এটি দেখতেও একই রকম মনে হবে। এটি লক্ষ্য ডিরেক্টরিটির একটি স্ট্যাটাস যুক্ত করেছে, এবং যুক্ত সাবশেল এবং পাইপের জন্য কিছু ওভারহেড।


-2

আমি মনে করি ইকো * যে কোনও 'ls' কমান্ডের চেয়ে বেশি দক্ষ হবে:

echo * | wc -w

4
তাদের নামে একটি স্থান সহ ফাইলগুলি কী? echo 'Hello World'|wc -wউত্পাদন 2
জোসেফ আর।

@JosephR। ক্যাভেট এমপোটার
ড্যান গার্থওয়েট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.