নির্দিষ্ট এক্সটেনশান এবং তারা যে ডিরেক্টরিতে রয়েছে সেগুলি দিয়ে আমি কীভাবে ফাইলগুলি গণনা করব?


14

.cএকটি বৃহত জটিল ডিরেক্টরি কাঠামোর মধ্যে কতগুলি নিয়মিত ফাইলের এক্সটেনশন রয়েছে এবং এই ফাইলগুলি কতগুলি ডিরেক্টরিতে ছড়িয়ে রয়েছে তা আমি জানতে চাই। আউটপুট আমি চাই মাত্র এই দুটি সংখ্যা।

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

  • আমার ফাইলের নামগুলিতে (ডিরেক্টরি সহ) কোনও অক্ষর থাকতে পারে; তারা শুরু হতে পারে .বা -এবং স্পেস বা নতুন লাইন আছে।
  • আমার কিছু সিমলিংক থাকতে পারে যার নামগুলি শেষ হয়ে গেছে .cএবং ডিরেক্টরিগুলিতে সিমলিংক রয়েছে। আমি চাই না যে সিমলিংকগুলি অনুসরণ করা বা গণনা করা হোক বা আমি কমপক্ষে জানতে চাই যে সেগুলি কখন গণনা করা হচ্ছে।
  • ডিরেক্টরি কাঠামোর অনেকগুলি স্তর রয়েছে এবং শীর্ষ স্তরের ডিরেক্টরিতে (কর্মক্ষম ডিরেক্টরি) এতে কমপক্ষে একটি .cফাইল থাকে।

আমি তাড়াতাড়ি করে (বাশ) শেলের মধ্যে কিছু কমান্ড লিখেছি সেগুলি নিজেকে গণনা করার জন্য, তবে ফলাফলটি সঠিক বলে আমি মনে করি না ...

shopt -s dotglob
shopt -s globstar
mkdir out
for d in **/; do
     find "$d" -maxdepth 1 -type f -name "*.c" >> out/$(basename "$d")
done
ls -1Aq out | wc -l
cat out/* | wc -l

এটি অস্পষ্ট পুনঃনির্দেশ সম্পর্কে অভিযোগগুলি প্রকাশ করে, বর্তমান ডিরেক্টরিতে ফাইলগুলি মিস করে এবং বিশেষ অক্ষরগুলিতে ট্রিপ আপ করে (উদাহরণস্বরূপ, পুনঃনির্দেশিত findআউটপুট ফাইলের নামগুলিতে নিউলাইনগুলি প্রিন্ট করে ) এবং খালি ফাইলগুলির পুরো গুচ্ছ (ওফস) লিখেছে।

আমি কীভাবে আমার .cফাইলগুলি এবং সেগুলি ধারণ করে থাকা ডিরেক্টরিগুলি নির্ভরযোগ্যভাবে গণনা করতে পারি ?


যদি এটি সহায়তা করে তবে খারাপ নাম এবং প্রতিলিঙ্ক সহ একটি পরীক্ষা কাঠামো তৈরি করার জন্য এখানে কয়েকটি আদেশ রয়েছে:

mkdir -p cfiles/{1..3}/{a..b} && cd cfiles
mkdir space\ d
touch -- i.c -.c bad\ .c 'terrible
.c' not-c .hidden.c
for d in space\ d 1 2 2/{a..b} 3/b; do cp -t "$d" -- *.c; done
ln -s 2 dirlink
ln -s 3/b/i.c filelink.c

ফলাফলের কাঠামোর মধ্যে 7 টি ডিরেক্টরিতে .cফাইল থাকে এবং 29 নিয়মিত ফাইলগুলি শেষ হয় .c(যদি dotglobকমান্ডগুলি চালিত হয় বন্ধ থাকে) (যদি আমি ভুল করে ফেলেছি তবে দয়া করে আমাকে জানান)। এই আমি চাই নম্বর।

দয়া করে এই বিশেষ পরীক্ষাটি ব্যবহার না করে নির্দ্বিধায় ।

এনবি: যে কোনও শেল বা অন্য ভাষায় উত্তরগুলি আমার দ্বারা পরীক্ষা করা হবে এবং প্রশংসা করা হবে। আমার যদি নতুন প্যাকেজ ইনস্টল করতে হয় তবে সমস্যা নেই। আপনি যদি কোনও জিইউআই সমাধান জানেন, আমি আপনাকে ভাগ করে নিতে উত্সাহিত করি (তবে এটি পরীক্ষার জন্য আমি পুরো ডিই ইনস্টল করতে পারে না) :) আমি উবুন্টু মেট 17.10 ব্যবহার করি।


খারাপ প্রোগ্রামিং অভ্যাসের সাথে মোকাবিলা করার জন্য একটি প্রোগ্রাম লেখা বেশ চ্যালেঞ্জিং বলে প্রমাণিত হয়েছিল;)
উইনউনুছুস ইউনিক্স

উত্তর:


16

আমি প্রতিলিপি দিয়ে আউটপুট পরীক্ষা করেছি না তবে:

find . -type f -iname '*.c' -printf '%h\0' |
  sort -z |
  uniq -zc |
  sed -zr 's/([0-9]) .*/\1 1/' |
  tr '\0' '\n' |
  awk '{f += $1; d += $2} END {print f, d}'
  • findকমান্ড প্রতিটি ডিরেক্টরির নাম ছাপে .cএটি খুঁজে বের করে ফাইল।
  • sort | uniq -cপ্রতিটি ডিরেক্টরিতে কতগুলি ফাইল রয়েছে তা আমাদের দেবে ( sortসম্ভবত এখানে অপ্রয়োজনীয়, নিশ্চিত নয়)
  • এর সাথে sed, আমি ডিরেক্টরি নামটি প্রতিস্থাপন করি 1, এইভাবে সম্ভব সমস্ত অদ্ভুত অক্ষরগুলি সরিয়ে, কেবল গণনা সহ এবং 1অবশিষ্ট
  • আমাকে নতুনলাইন-বিচ্ছিন্ন আউটপুটটিতে রূপান্তর করতে সক্ষম করে tr
  • এটির পরে আমি মোটগুলি সংখ্যার সাথে যোগ করব, ফাইলগুলির মোট সংখ্যা এবং এই ফাইলগুলিতে থাকা ডিরেক্টরিগুলির সংখ্যা। নোট করুন যে dএখানে মূলত একই NR। আমি ঢোকাতে বাদ দেওয়া থাকতে পারে 1sedকমান্ড এবং মাত্র মুদ্রিত NRএখানে, কিন্তু আমি মনে করি এটা সামান্য পরিস্কার হয়।

অবধি tr, ডেটাটি NUL- সীমাবদ্ধ, সমস্ত বৈধ ফাইল নামের বিরুদ্ধে নিরাপদ।


Zsh এবং bash এর সাহায্যে আপনি printf %qএকটি উদ্ধৃত স্ট্রিং পেতে ব্যবহার করতে পারেন , এতে নতুন লাইন থাকবে না। সুতরাং, আপনি এর মতো কিছু করতে সক্ষম হতে পারেন:

shopt -s globstar dotglob nocaseglob
printf "%q\n" **/*.c | awk -F/ '{NF--; f++} !c[$0]++{d++} END {print f, d}'

যাইহোক, যদিও **ডিরেক্টরিগুলিতে সিমলিংকের জন্য প্রসারিত হওয়ার কথা না , তবে আমি ব্যাশ ৪.৪.১৮ (১) (উবুন্টু ১.0.০৪) এ পছন্দসই আউটপুট পেতে পারি না।

$ shopt -s globstar dotglob nocaseglob
$ printf "%q\n" ./**/*.c | awk -F/ '{NF--; f++} !c[$0]++{d++} END {print f, d}'
34 15
$ echo $BASH_VERSION
4.4.18(1)-release

তবে zsh ভাল কাজ করেছে, এবং কমান্ডটি সহজ করা যেতে পারে:

$ printf "%q\n" ./**/*.c(D.:h) | awk '!c[$0]++ {d++} END {print NR, d}'
29 7

Dএই গ্লোবকে ডট ফাইলগুলি নির্বাচন করতে সক্ষম করে, .নিয়মিত ফাইল নির্বাচন করে (সুতরাং, সিমলিংক নয়), এবং :hকেবল ডিরেক্টরি পাথ প্রিন্ট করে না ফাইলের নাম (যেমন findএর %h) ( ফাইলের নাম জেনারেশন এবং সংশোধকগুলির বিভাগ দেখুন )। সুতরাং awk কমান্ডের সাহায্যে আমাদের কেবল উপস্থিত অনন্য ডিরেক্টরিগুলির সংখ্যা গণনা করতে হবে এবং লাইনের সংখ্যাটি ফাইল গণনা।


সেটা খুবই ভালো. যা প্রয়োজন ঠিক তেমন ব্যবহার করে এবং আর কিছুই না। শিক্ষকতার জন্য আপনাকে ধন্যবাদ :)
Zanna

@ জান্না আপনি যদি সিমলিংক সহ ডিরেক্টরি কাঠামো এবং সিমলিংকের সাহায্যে প্রত্যাশিত আউটপুট পুনরায় তৈরি করতে কিছু কমান্ড পোস্ট করেন তবে আমি সে অনুযায়ী এটি ঠিক করতে সক্ষম হতে পারি।
মুড়ু

সিমলিঙ্কগুলি দিয়ে একটি (অযথা জটিল জটিল) পরীক্ষার কাঠামো তৈরি করতে আমি কয়েকটি কমান্ড যুক্ত করেছি।
জান্না

@ জান্না আমি মনে করি এই কমান্ডটি পেতে কোনও সামঞ্জস্যের প্রয়োজন নেই 29 7। যদি আমি যোগ -Lকরতে find, যে পর্যন্ত যায় 41 10। আপনার কোন আউটপুট দরকার?
মুড়ু

1
একটি zsh + awk পদ্ধতি যুক্ত করা হয়েছে। আমার জন্য কাউন্টটি মুদ্রণের জন্য সম্ভবত zsh পাওয়ার কিছু উপায় আছে তবে কীভাবে তা জানা যায় না।
মুড়ু

11

পাইথন রয়েছে os.walk, যা এই সহজ, স্বজ্ঞাত এবং স্বয়ংক্রিয়ভাবে এমনকি অদ্ভুত ফাইলনামগুলির মতো এমনকি শক্তিশালী করে যেমন নিউলাইন চরিত্রগুলি ধারণ করে। এই পাইথন 3 স্ক্রিপ্টটি, যা আমি মূলত চ্যাটে পোস্ট করেছিলাম তা বর্তমান ডিরেক্টরিতে চালিত করার উদ্দেশ্যে করা হয়েছে (তবে এটি বর্তমান ডিরেক্টরিতে অবস্থিত হবে না এবং আপনি এটি কোন পথে যেতে পারেন তা পরিবর্তন করতে পারেন os.walk):

#!/usr/bin/env python3

import os

dc = fc = 0
for _, _, fs in os.walk('.'):
    c = sum(f.endswith('.c') for f in fs)
    if c:
        dc += 1
        fc += c
print(dc, fc)

এটি ডিরেক্টরিগুলির গণনা প্রিন্ট করে যেগুলিতে সরাসরি অন্তত একটি ফাইল থাকে যার নাম শেষ হয় .c, একটি স্থান পরে, যার পরে ফাইলগুলির নাম শেষ হয় .c। "লুকানো" ফাইলগুলি - .অর্থাত, যাদের নামগুলি --are অন্তর্ভুক্ত থাকে এবং গোপন ডিরেক্টরিগুলি একইভাবে অনুসরণ করা হয়।

os.walkপুনরাবৃত্তভাবে একটি ডিরেক্টরি শ্রেণিবিন্যাসকে অনুসরণ করে। এটি সমস্ত ডিরেক্টরি সূচিত করে যা আপনি যে শুরুর দিকটি দিয়ে থাকেন তা থেকে পুনরাবৃত্তিযোগ্যভাবে অ্যাক্সেসযোগ্য এবং তাদের প্রত্যেককে তিনটি মানের একটি টিপল হিসাবে তথ্য প্রদান করে root, dirs, files,। প্রতিটি ডিরেক্টরিতে এটি প্রবেশ করে (প্রথমটির যার সাথে আপনি এটি দিয়েছিলেন):

  • rootএই ডিরেক্টরিটির পথের নামটি ধারণ করে। দ্রষ্টব্য যে এটি সম্পূর্ণরূপে সিস্টেমের "রুট ডিরেক্টরি" /(এবং এর সাথে সম্পর্কিত নয় /root) এর সাথেও সম্পর্কিত নয় যদিও এটি যদি আপনি সেখানে শুরু করেন তবে এটি তাদের কাছে যাবে। এই ক্ষেত্রে, rootপাথ আরম্ভ করা হয় .--ie, বর্তমান ডিরেক্টরির - এবং এটি নীচের সর্বত্র যায়।
  • dirsডিরেক্টরিতে যার নাম বর্তমানে অধিষ্ঠিত রয়েছে তার সমস্ত সাব - ডাইরেক্টরির পাথের নামের একটি তালিকা রয়েছে root
  • filesডিরেক্টরিতে থাকা সমস্ত ফাইলের নামের নামের একটি তালিকা রয়েছে যার নাম বর্তমানে রয়েছে rootতবে সেগুলি নিজেরাই ডিরেক্টরি নয়। দ্রষ্টব্য যে এটিতে নিয়মিত ফাইলের তুলনায় অন্যান্য ধরণের ফাইল অন্তর্ভুক্ত রয়েছে, প্রতীকী লিঙ্কগুলি সহ, তবে মনে হয় আপনি এই জাতীয় কোনও এন্ট্রি শেষ হওয়ার আশা করেন না .cএবং এটি যে কোনও কাজ করতে আগ্রহী।

এই ক্ষেত্রে, আমাকে কেবল টিপলের তৃতীয় উপাদানটি পরীক্ষা করতে হবে, files(যা আমি fsস্ক্রিপ্টে ডাকি )। findকমান্ডটির মতো পাইথনের os.walkআমার জন্য সাব-ডাইরেক্টরিতে রূপান্তরিত হয়; কেবলমাত্র আমাকে নিজেরাই যাচাই করতে হবে সেগুলির মধ্যে প্রতিটি ফাইলের নাম। findকমান্ডের বিপরীতে , যদিও, os.walkস্বয়ংক্রিয়ভাবে আমাকে সেই ফাইলগুলির একটি তালিকা সরবরাহ করে।

এই লিপিটি প্রতীকী লিঙ্কগুলি অনুসরণ করে না। আপনি সম্ভবত চান না যে এ জাতীয় ক্রিয়াকলাপের জন্য অনুসরণ করা সিমলিংকগুলি চক্র তৈরি করতে পারে এবং কারণ সেখানে চক্র না থাকলেও একই ফাইল এবং ডিরেক্টরিগুলি বিভিন্ন সিমলিংকের মাধ্যমে অ্যাক্সেসযোগ্য হলে একাধিকবার ট্র্যাভারড এবং গণনা করা যেতে পারে।

আপনি যদি os.walkসিমলিঙ্কগুলি কখনও অনুসরণ করতে চান না - যা আপনি সাধারণত না করেন - তবে আপনি followlinks=trueএটিতে যেতে পারেন। অর্থাৎ লেখার পরিবর্তে os.walk('.')আপনি লিখতে পারতেন os.walk('.', followlinks=true)। আমি আবারও বলছি যে আপনি খুব কমই এটি চাইবেন, বিশেষত এমন একটি কাজের জন্য যেখানে আপনি বারবার ক্রমবর্ধমান একটি সম্পূর্ণ ডিরেক্টরি কাঠামো গণনা করছেন, এটি যত বড়ই হোক না কেন, এবং এতে সমস্ত ফাইলগুলি গণনা করা হচ্ছে যা কিছু প্রয়োজনীয়তা পূরণ করে।


7

পার্ল সন্ধান করুন:

$ find . -type f -iname '*.c' -printf '%h\0' | 
    perl -0 -ne '$k{$_}++; }{ print scalar keys %k, " $.\n" '
7 29

ব্যাখ্যা

find(তাই কোন symlinks বা ডিরেক্টরি) কমান্ড কোনো নিয়মিত ফাইল পাবেন এবং তারপর ডিরেক্টরীর নাম তারা রয়েছে মুদ্রণ ( %h) দ্বারা অনুসৃত \0

  • perl -0 -ne: লাইন দ্বারা ইনপুট লাইনটি পড়ুন ( -n) এবং -eপ্রতিটি লাইনের দ্বারা প্রদত্ত স্ক্রিপ্টটি প্রয়োগ করুন । -0ইনপুট লাইন বিভাজক সেট করে \0তাই আমরা নাল-সীমা নির্দেশ করা ইনপুট পড়তে পারেন।
  • $k{$_}++: $_একটি বিশেষ পরিবর্তনশীল যা বর্তমান লাইনের মান গ্রহণ করে। এটি হ্যাশটির কী হিসাবে ব্যবহৃত হয় %k, যার মান প্রতিটি ইনপুট লাইন (ডিরেক্টরি নাম) দেখাবারের সংখ্যা।
  • }{: এটি লেখার একটি সংক্ষিপ্ত উপায় END{}}{সমস্ত ইনপুট প্রক্রিয়া করার পরে, এর পরে কোনও কমান্ড একবার কার্যকর করা হবে।
  • print scalar keys %k, " $.\n": keys %kহ্যাশটিতে কীগুলির একটি অ্যারের প্রদান করে %kscalar keys %kঅ্যারেতে উপাদানগুলির সংখ্যা দেয়, ডিরেক্টরিগুলির সংখ্যা দেখায়। এটি বর্তমান মানের $.ইনপুট লাইন নম্বরটি ধারণ করে একটি বিশেষ ভেরিয়েবলের সাথে মুদ্রিত হয় । যেহেতু এটি শেষে চালিত হয়, বর্তমান ইনপুট লাইন নম্বরটি শেষ লাইনের সংখ্যা হবে, সুতরাং এখন পর্যন্ত দেখা লাইনের সংখ্যা।

স্পষ্টতার জন্য আপনি পার্ল কমান্ডটি এটিতে প্রসারিত করতে পারেন:

find  . -type f -iname '*.c' -printf '%h\0' | 
    perl -0 -e 'while($line = <STDIN>){
                    $dirs{$line}++; 
                    $tot++;
                } 
                $count = scalar keys %dirs; 
                print "$count $tot\n" '

4

আমার পরামর্শটি এখানে:

#!/bin/bash
tempfile=$(mktemp)
find -type f -name "*.c" -prune >$tempfile
grep -c / $tempfile
sed 's_[^/]*$__' $tempfile | sort -u | grep -c /

এই সংক্ষিপ্ত স্ক্রিপ্টটি একটি টেম্পাইল তৈরি করে, বর্তমান ডিরেক্টরিটি অন্তর্ভুক্ত বর্তমান ফাইলের ভিতরে এবং নীচে থাকা প্রতিটি ফাইলকে খুঁজে বের করে .cএবং তালিকাটি টেমপ্লেলে লিখে দেয়। grepতারপরে ফাইলগুলি গণনা করার জন্য ব্যবহৃত হয় ( কমান্ড লাইনটি ব্যবহার করে কোনও ডিরেক্টরিতে আমি ফাইলগুলির একটি গণনা কীভাবে পেতে পারি? ): দ্বিতীয় বার, একাধিকবার তালিকাভুক্ত ডিরেক্টরিগুলি sort -uপ্রতিটি লাইন থেকে ফাইলের নামগুলি ব্যবহার করে সরিয়ে ফেলা হবে sed

এটি ফাইলনেমগুলিতে নতুন grep -c /লাইনের সাথে সঠিকভাবে কাজ করে: একটি স্ল্যাশ সহ কেবলমাত্র লাইন গণনা করে এবং তাই তালিকার একাধিক-লাইন ফাইলনামের কেবল প্রথম লাইন বিবেচনা করে।

আউটপুট

$ tree
.
├── 1
   ├── 1
      ├── test2.c
      └── test.c
   └── 2
       └── test.c
└── 2
    ├── 1
       └── test.c
    └── 2

$ tempfile=$(mktemp);find -type f -name "*.c" -prune >$tempfile;grep -c / $tempfile;sed 's_[^/]*$__' $tempfile | sort -u | grep -c /
4
3

4

ছোট শেলসক্রিপ্ট

আমি দুটি প্রধান কমান্ড লাইন (এবং filetypeঅন্যান্য ফাইলের সন্ধানের জন্য স্যুইচ করা সহজ করার জন্য একটি ভেরিয়েবল) সহ একটি ছোট বাশ শেলস্ক্রিপ্ট প্রস্তাব করি ।

এটি কেবল নিয়মিত ফাইলগুলির জন্য বা সিমলিঙ্কগুলিতে সন্ধান করে না।

#!/bin/bash

filetype=c
#filetype=pdf

# count the 'filetype' files

find -type f -name "*.$filetype" -ls|sed 's#.* \./##'|wc -l | tr '\n' ' '

# count directories containing 'filetype' files

find -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)'" \;|grep 'contains file(s)$'|wc -l

ভার্বোজ শেলসক্রিপ্ট

এটি একটি আরও ভার্বোজ সংস্করণ যা প্রতীকী লিঙ্কগুলিও বিবেচনা করে,

#!/bin/bash

filetype=c
#filetype=pdf

# counting the 'filetype' files

echo -n "number of $filetype files in the current directory tree: "
find -type f -name "*.$filetype" -ls|sed 's#.* \./##'|wc -l

echo -n "number of $filetype symbolic links in the current directory tree: "
find -type l -name "*.$filetype" -ls|sed 's#.* \./##'|wc -l
echo -n "number of $filetype normal files in the current directory tree: "
find -type f -name "*.$filetype" -ls|sed 's#.* \./##'|wc -l
echo -n "number of $filetype symbolic links in the current directory tree including linked directories: "
find -L -type f -name "*.$filetype" -ls 2> /tmp/c-counter |sed 's#.* \./##' | wc -l; cat /tmp/c-counter; rm /tmp/c-counter

# list directories with and without 'filetype' files (good for manual checking; comment away after test)
echo '---------- list directories:'
 find    -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)' || echo '{} empty'" \;
echo ''
#find -L -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)' || echo '{} empty'" \;

# count directories containing 'filetype' files

echo -n "number of directories with $filetype files: "
find -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)'" \;|grep 'contains file(s)$'|wc -l

# list and count directories including symbolic links, containing 'filetype' files
echo '---------- list all directories including symbolic links:'
find -L -type d -exec bash -c "ls -AF '{}' |grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)' || echo '{} empty'" \;
echo ''
echo -n "number of directories (including symbolic links) with $filetype files: "
find -L -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)'" \; 2>/dev/null |grep 'contains file(s)$'|wc -l

# count directories without 'filetype' files (good for checking; comment away after test)

echo -n "number of directories without $filetype files: "
find -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null || echo '{} empty'" \;|grep 'empty$'|wc -l

টেস্ট আউটপুট

সংক্ষিপ্ত শেলসক্রিপ্ট থেকে:

$ ./ccntr 
29 7

ভার্জোজ শেলসক্রিপ্ট থেকে:

$ LANG=C ./c-counter
number of c files in the current directory tree: 29
number of c symbolic links in the current directory tree: 1
number of c normal files in the current directory tree: 29
number of c symbolic links in the current directory tree including linked directories: 42
find: './cfiles/2/2': Too many levels of symbolic links
find: './cfiles/dirlink/2': Too many levels of symbolic links
---------- list directories:
. empty
./cfiles contains file(s)
./cfiles/2 contains file(s)
./cfiles/2/b contains file(s)
./cfiles/2/a contains file(s)
./cfiles/3 empty
./cfiles/3/b contains file(s)
./cfiles/3/a empty
./cfiles/1 contains file(s)
./cfiles/1/b empty
./cfiles/1/a empty
./cfiles/space d contains file(s)

number of directories with c files: 7
---------- list all directories including symbolic links:
. empty
./cfiles contains file(s)
./cfiles/2 contains file(s)
find: './cfiles/2/2': Too many levels of symbolic links
./cfiles/2/b contains file(s)
./cfiles/2/a contains file(s)
./cfiles/3 empty
./cfiles/3/b contains file(s)
./cfiles/3/a empty
./cfiles/dirlink empty
find: './cfiles/dirlink/2': Too many levels of symbolic links
./cfiles/dirlink/b contains file(s)
./cfiles/dirlink/a contains file(s)
./cfiles/1 contains file(s)
./cfiles/1/b empty
./cfiles/1/a empty
./cfiles/space d contains file(s)

number of directories (including symbolic links) with c files: 9
number of directories without c files: 5
$ 

4

সাধারণ পার্ল ওয়ান লাইনার:

perl -MFile::Find=find -le'find(sub{/\.c\z/ and -f and $c{$File::Find::dir}=++$c}, @ARGV); print 0 + keys %c, " $c"' dir1 dir2

বা findকমান্ড সহ সহজ :

find dir1 dir2 -type f -name '*.c' -printf '%h\0' | perl -l -0ne'$c{$_}=1}{print 0 + keys %c, " $."'

আপনি যদি গল্ফিং পছন্দ করেন এবং সাম্প্রতিক (দশকেরও কম পুরানো মত) পার্ল:

perl -MFile::Find=find -E'find(sub{/\.c$/&&-f&&($c{$File::Find::dir}=++$c)},".");say 0+keys%c," $c"'
find -type f -name '*.c' -printf '%h\0'|perl -0nE'$c{$_}=1}{say 0+keys%c," $."'

2

locateকমান্ডের চেয়ে দ্রুততর কমান্ডটি ব্যবহার করার বিষয়টি বিবেচনা করুন find

পরীক্ষার ডেটাতে চলছে

$ sudo updatedb # necessary if files in focus were added `cron` daily.
$ printf "Number Files: " && locate -0r "$PWD.*\.c$" | xargs -0 -I{} sh -c 'test ! -L "$1" && echo "regular file"' _  {} | wc -l &&  printf "Number Dirs.: " && locate -r "$PWD.*\.c$" | sed 's%/[^/]*$%/%' | uniq -cu | wc -l
Number Files: 29
Number Dirs.: 7

ইউনিক্স এবং লিনাক্স উত্তরের ফাইল গণনা থেকে প্রতীকী লিঙ্কগুলি সরিয়ে দিয়ে আমাকে সহায়তা করার জন্য তার প্রশ্নের জবাব দেওয়ার জন্য মুরুকে ধন্যবাদ জানাই ।

ইউনিক্স এবং লিনাক্স উত্তরের উত্তর$PWD (আমার দিকে নির্দেশিত নয়) টেরডনের জন্য ধন্যবাদ ।


নীচে মূল উত্তর মন্তব্য দ্বারা রেফারেন্স

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

$ cd /
$ sudo updatedb
$ printf "Number Files: " && locate -cr "$PWD.*\.c$"
Number Files: 3523
$ printf "Number Dirs.: " && locate -r "$PWD.*\.c$" | sed 's%/[^/]*$%/%' | uniq -c | wc -l 
Number Dirs.: 648
  • sudo updatedbআজ ফাইল তৈরি করা হয় বা আপনি যদি আজ ফাইল মুছে ফেলে থাকেন তবে locateকমান্ড দ্বারা ব্যবহৃত ডাটাবেস আপডেট করুন ।.c.c
  • locate -cr "$PWD.*\.c$".cবর্তমান ডিরেক্টরিতে সমস্ত ফাইল সনাক্ত করুন এবং এটি শিশু ( $PWD)। ফাইলের নাম মুদ্রণের পরিবর্তে এবং -cযুক্তির সাথে মুদ্রণ গণনা count rনির্দিষ্ট করে ডিফল্ট পরিবর্তে Regex *pattern*ম্যাচিং যা অনেকগুলি ফলাফল উত্পাদ পারবেন না।
  • locate -r "$PWD.*\.c$" | sed 's%/[^/]*$%/%' | uniq -c | wc -l*.cবর্তমান ডিরেক্টরিতে এবং নীচে সমস্ত ফাইল সন্ধান করুন । sedকেবল ডিরেক্টরি নাম রেখে ফাইলের নাম সরান । প্রতিটি ডিরেক্টরি ব্যবহার করে ফাইলের সংখ্যা গণনা করুন uniq -c। এর সাথে ডিরেক্টরিগুলির সংখ্যা গণনা করুন wc -l

ওয়ান-লাইনার দিয়ে বর্তমান ডিরেক্টরিতে শুরু করুন

$ cd /usr/src
$ printf "Number Files: " && locate -cr "$PWD.*\.c$" &&  printf "Number Dirs.: " && locate -r "$PWD.*\.c$" | sed 's%/[^/]*$%/%' | uniq -c | wc -l
Number Files: 3430
Number Dirs.: 624

ফাইল গণনা এবং ডিরেক্টরি গণনা কিভাবে পরিবর্তিত হয়েছে তা লক্ষ্য করুন। আমি বিশ্বাস করি যে সমস্ত ব্যবহারকারীর /usr/srcডিরেক্টরি আছে এবং ইনস্টল করা কার্নেলের সংখ্যার উপর নির্ভর করে বিভিন্ন গণনা সহ উপরের কমান্ডগুলি চালাতে পারে।

দীর্ঘ ফর্ম:

দীর্ঘ ফর্মটিতে সময় অন্তর্ভুক্ত রয়েছে যাতে আপনি দেখতে পান যে কত দ্রুত locateশেষ find। এমনকি যদি sudo updatedbএটি চালাতে হয় তবে এটি এককটির চেয়ে বহুগুণ দ্রুত find /

───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/Downloads$ sudo time updatedb
0.58user 1.32system 0:03.94elapsed 48%CPU (0avgtext+0avgdata 7568maxresident)k
48inputs+131920outputs (1major+3562minor)pagefaults 0swaps
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/Downloads$ time (printf "Number Files: " && locate -cr $PWD".*\.c$")
Number Files: 3523

real    0m0.775s
user    0m0.766s
sys     0m0.012s
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/Downloads$ time (printf "Number Dirs.: " && locate -r $PWD".*\.c$" | sed 's%/[^/]*$%/%' | uniq -c | wc -l) 
Number Dirs.: 648

real    0m0.778s
user    0m0.788s
sys     0m0.027s
───────────────────────────────────────────────────────────────────────────────────────────

দ্রষ্টব্য: এটি সমস্ত ড্রাইভ এবং পার্টিশনের সমস্ত ফাইল । যেমন আমরা উইন্ডোজ কমান্ডগুলিও অনুসন্ধান করতে পারি:

$ time (printf "Number Files: " && locate *.exe -c)
Number Files: 6541

real    0m0.946s
user    0m0.761s
sys     0m0.060s
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/Downloads$ time (printf "Number Dirs.: " && locate *.exe | sed 's%/[^/]*$%/%' | uniq -c | wc -l) 
Number Dirs.: 3394

real    0m0.942s
user    0m0.803s
sys     0m0.092s

আমার তিনটি উইন্ডোজ 10 এনটিএফএস পার্টিশন স্বয়ংক্রিয়ভাবে মাউন্ট হয়েছে /etc/fstab। সচেতন হতে সব কিছু জানেন!

আকর্ষণীয় গণনা:

$ time (printf "Number Files: " && locate / -c &&  printf "Number Dirs.: " && locate / | sed 's%/[^/]*$%/%' | uniq -c | wc -l)
Number Files: 1637135
Number Dirs.: 286705

real    0m15.460s
user    0m13.471s
sys     0m2.786s

286,705 ডিরেক্টরিতে 1,637,135 ফাইল গণনা করতে 15 সেকেন্ড সময় লাগে। YMMV।

locateকমান্ডের রেজেক্স হ্যান্ডলিংয়ের বিস্তারিত ভাঙ্গনের জন্য (এই প্রশ্নোত্তরটিতে প্রয়োজন হবে না তবে কেবল ক্ষেত্রে ব্যবহৃত হয়েছে) দয়া করে এটি পড়ুন: কিছু নির্দিষ্ট ডিরেক্টরিতে "চিহ্নিত" ব্যবহার করবেন?

সাম্প্রতিক নিবন্ধগুলি থেকে অতিরিক্ত পড়া:


1
এটি কোনও নির্দিষ্ট ডিরেক্টরিতে ফাইলগুলি গণনা করে না। আপনি যেমন উল্লেখ করেছেন, এটি সমস্ত ফাইল (বা ডিরেক্টরিগুলি, বা অন্য কোনও ধরণের ফাইল) মেলাতে গণনা করে .c(নোট করুন যে -.cবর্তমান ডিরেক্টরিতে কোনও ফাইলের নাম নেই যদি এটি উদ্ধৃত না করে এটি ভেঙে যাবে *.c) এবং তারপরে এটি সমস্ত ডিরেক্টরি মুদ্রণ করবে সিস্টেমে, সেগুলিতে .c ফাইল রয়েছে কিনা তা নির্বিশেষে।
টেরডন

@terdon আপনি একটি ডিরেক্টরি পাস করতে পারেন ~/my_c_progs/*.c। এটি .cপ্রোগ্রাম সহ 638 ডিরেক্টরি গণনা করছে , মোট ডিরেক্টরি পরে দেখানো হবে 286,705। আমি ডাবল উক্তিটির উত্তরটি সংশোধন করব `" * .সি "। টিপ জন্য ধন্যবাদ.
WinEunuuchs2Unix

3
হ্যাঁ, আপনি এর মতো কিছু ব্যবহার করতে পারেন locate -r "/path/to/dir/.*\.c$"তবে এটি আপনার উত্তরের কোথাও উল্লেখ করা হয়নি। আপনি কেবলমাত্র অন্য একটি উত্তরের একটি লিঙ্ক দিন যা এতে উল্লেখ রয়েছে তবে এখানে জিজ্ঞাসিত প্রশ্নের উত্তরটি কীভাবে খাপ খাইয়ে নেওয়া যায় তার কোনও ব্যাখ্যা ছাড়াই। আপনার পুরো উত্তরটি সিস্টেমে ফাইল এবং ডিরেক্টরিগুলির মোট সংখ্যা কীভাবে গণনা করতে হবে তার উপর কেন্দ্রীভূত, যা জিজ্ঞাসা করা প্রশ্নটির সাথে প্রাসঙ্গিক নয় যে "আমি কীভাবে .c ফাইলের সংখ্যা এবং কীভাবে ডিরেক্টরি রয়েছে সেগুলি গণনা করতে পারি?" একটি নির্দিষ্ট ডিরেক্টরিতে সি ফাইল "। এছাড়াও, আপনার নম্বরগুলি ভুল, ওপিতে উদাহরণটিতে চেষ্টা করে দেখুন।
টেরডন

@ ইটারডন আপনার ইনপুট জন্য ধন্যবাদ। আমি আপনার পরামর্শগুলির সাথে উত্তরটি পরিবর্তন করেছি এবং একটি উত্তর আপনি $PWDভেরিয়েবলের জন্য অন্যান্য এসই সাইটে পোস্ট করেছেন : unix.stackexchange.com/a/188191/200094
WinEunuuchs2Unix

1
এখন আপনাকে অবশ্যই নিশ্চিত করতে হবে যে $PWDএমন কোনও অক্ষর নেই যা সম্ভবত একটি রেইজেক্সে বিশেষ
মুড়ু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.