উত্তর:
এই সহজ ওয়ানলাইনারটি কেবল বাশ নয়, যে কোনও শেলটিতে কাজ করা উচিত:
ls -1q log* | wc -l
ls -1q আপনাকে ফাইল প্রতি এক লাইন দেবে, এমনকি তাতে সাদা অংশ বা নিউলাইনগুলির মতো বিশেষ অক্ষর রয়েছে।
আউটপুটটি ডাব্লুসি-এল-তে পাইপ করা হয়, যা রেখার সংখ্যা গণনা করে।
ls
এটি ব্যবহার করব না , যেহেতু এটি একটি শিশু প্রক্রিয়া তৈরি করে। log*
শেল দ্বারা প্রসারিত হয়, না ls
, তাই একটি সাধারণ echo
কি না।
logs
জিজ্ঞাসাবাদযুক্ত বলা হয়, তবে সেই লগ ডিরেক্টরিগুলির বিষয়বস্তুও গণনা করা হবে। এটি সম্ভবত উদ্দেশ্যমূলক নয়।
আপনি এটি নিরাপদে করতে পারেন (অর্থাত্ স্পেসের সাথে বা \n
তাদের নামে কোনও ফাইল বুগ হবে না ):
$ shopt -s nullglob
$ logfiles=(*.log)
$ echo ${#logfiles[@]}
আপনাকে সক্ষম করতে হবে nullglob
যাতে কোনও ফাইলের মিল না থাকলে *.log
আপনি $logfiles
অ্যারেতে আক্ষরিক না পান । ( কীভাবে নিরাপদে পুনরায় সেট করা যায় তার উদাহরণগুলির জন্য 'সেট-এক্স' কীভাবে "পূর্বাবস্থাপন করবেন" দেখুন ))
shopt -u nullglob
বাদ দেওয়া উচিত যদি nullglob
সেট না করা থাকে তবে আপনি শুরু করেছিলেন।
*.log
সঙ্গে মাত্র *
ডিরেক্টরি গণনা করা হবে। আপনি যে ফাইলগুলি গণনা করতে চান সেগুলির চিরায়ত নামকরণের কনভেনশন থাকলে name.extension
, ব্যবহার করুন *.*
।
এখানে প্রচুর উত্তর, কিন্তু কিছু বিবেচনায় নেই
-l
)*.log
পরিবর্তে এটি হয়log*
logs
যা মেলে log*
)এখানে একটি সমাধান যা এগুলি সমস্তকে পরিচালনা করে:
ls 2>/dev/null -Ubad1 -- log* | wc -l
ব্যাখ্যা:
-U
ls
এন্ট্রিগুলি বাছাই না করার কারণ , এর জন্য এটি মেমরির সম্পূর্ণ ডিরেক্টরি তালিকা লোড করার প্রয়োজন হয় না-b
মুদ্রণ সি স্টাইলটি নংগ্রাফিক চরিত্রগুলির জন্য পালিয়ে যায়, ফলে নিউলাইনগুলি মুদ্রিত হওয়ার কারণ হয় \n
।-a
সমস্ত ফাইল মুদ্রণ করে এমনকি গোপনীয় ফাইলগুলি (যখন গ্লোব log*
কোনও লুকানো ফাইল বোঝায় তখন কঠোরভাবে প্রয়োজন হয় না )-d
ডিরেক্টরিগুলির বিষয়বস্তু তালিকাভুক্ত করার চেষ্টা না করে ডিরেক্টরি মুদ্রণ করে , যা ls
সাধারণত হয়-1
এটি একটি কলামে রয়েছে তা নিশ্চিত করে (পাইপে লেখার সময় ls স্বয়ংক্রিয়ভাবে এটি করে, তাই এটি কঠোরভাবে প্রয়োজনীয় নয়)2>/dev/null
স্ট্যাডারকে পুনঃনির্দেশ করে যাতে 0 লগ ফাইল থাকে তবে ত্রুটি বার্তাকে উপেক্ষা করুন। (দ্রষ্টব্য যা এর পরিবর্তে পুরো কার্য ডিরেক্টরিকে তালিকাভুক্ত shopt -s nullglob
করবে would ls
)wc -l
ডিরেক্টরি তৈরি হওয়ার সাথে সাথে তালিকা তালিকাটি গ্রহন করে, তাই এর ফলে আউটপুট ls
কখনই মেমরির হয় না time--
ফাইলের নামগুলি ব্যবহার করে কমান্ড থেকে পৃথক করা হয়েছে --
যাতে আর্গুমেন্ট হিসাবে বোঝা না যায় ls
(ক্ষেত্রে log*
সরিয়ে ফেলা হয়)শেলটি ফাইলের সম্পূর্ণ তালিকায় প্রসারিত হবেlog*
, যা প্রচুর ফাইল থাকলে মেমরিটি নিঃশেষ করে দিতে পারে, সুতরাং গ্রিপের মাধ্যমে এটি চালানো আরও ভাল:
ls -Uba1 | grep ^log | wc -l
এটি সর্বশেষে প্রচুর মেমরি ব্যবহার না করেই ফাইলগুলির অত্যন্ত বড় ডিরেক্টরি পরিচালনা করে (যদিও এটি সাবসেল ব্যবহার করে না)। -d
আর প্রয়োজনীয় কারণ এটি শুধুমাত্র বর্তমান ডিরেক্টরির বিষয়বস্তু তালিকা হচ্ছে হয়।
পুনরাবৃত্ত অনুসন্ধানের জন্য:
find . -type f -name '*.log' -printf x | wc -c
wc -c
এর ফলাফলের মধ্যে অক্ষরের সংখ্যা গণনা করবে find
, যখন প্রতিটি ফলাফলের জন্য একটি একক মুদ্রণ করতে -printf x
বলে tellsfind
x
একটি পুনরাবৃত্তি অনুসন্ধানের জন্য, এটি করুন:
find . -maxdepth 1 -type f -name '*.log' -printf x | wc -c
-name '*.log'
তবে এটি সমস্ত ফাইল গণনা করবে, যা আমার ব্যবহারের ক্ষেত্রে প্রয়োজন। এছাড়াও -ম্যাক্সডেপথ পতাকাটি অত্যন্ত কার্যকর, ধন্যবাদ!
find
; ভারব্যাটিম ফাইলের নাম ছাড়া আর কিছু মুদ্রণ করুন।
এই প্রশ্নের জন্য গৃহীত উত্তরটি ভুল, তবে আমার কাছে কম রেপ রয়েছে তাই এটিতে কোনও মন্তব্য যুক্ত করতে পারি না।
এই প্রশ্নের সঠিক উত্তর ম্যাট দিয়েছেন:
shopt -s nullglob
logfiles=(*.log)
echo ${#logfiles[@]}
গৃহীত উত্তরের সাথে সমস্যাটি হ'ল ডাব্লুসি-এল নতুন লাইনের চরিত্রগুলির সংখ্যা গণনা করে এবং তারা 'টার্মিনালে প্রিন্ট করেও তাদের গণনা করে?' 'ls -l' এর আউটপুট এ। এর অর্থ হ'ল কোনও ফাইলনামে একটি নতুন লাইনের চরিত্র থাকা অবস্থায় গৃহীত উত্তরটি ব্যর্থ হয়। আমি প্রস্তাবিত আদেশটি পরীক্ষা করেছি:
ls -l log* | wc -l
এবং এটি ভ্রান্তভাবে 2 টির মান প্রতিবেদন করে এমনকি এমন যদি 1 টি ফাইলের সাথে মেলে যা এর নামের সাথে একটি নতুন লাইনের চরিত্র ধারণ করে। উদাহরণ স্বরূপ:
touch log$'\n'def
ls log* -l | wc -l
যদি আপনার কাছে প্রচুর ফাইল থাকে এবং আপনি মার্জিত shopt -s nullglob
এবং ব্যাশ অ্যারের সমাধানটি ব্যবহার করতে না চান , আপনি যতক্ষণ না ফাইল নাম মুদ্রণ না করেন (যেমন নিউলাইনগুলি থাকতে পারে) আপনি ফাইন্ড ইত্যাদি ব্যবহার করতে পারেন।
find -maxdepth 1 -name "log*" -not -name ".*" -printf '%i\n' | wc -l
এটি লগ * এর সাথে মেলে এমন সমস্ত ফাইল খুঁজে পাবে যা এর সাথে শুরু হয় না .*
- "নাম নয়। *" ফায়দা হ'ল, তবে এটি লক্ষণীয় গুরুত্বপূর্ণ যে "ls" এর জন্য ডিফল্টটি ডট-ফাইলগুলি প্রদর্শন না করা, তবে ডিফল্ট কারণ তাদের অন্তর্ভুক্ত করা হয়।
এটি একটি সঠিক উত্তর, এবং আপনি যে কোনও ধরণের ফাইলের নামটি ফেলে দিতে পারেন তা হ্যান্ডেল করে, কারণ ফাইলের নাম কখনই কমান্ডের মধ্যে অতিক্রম করে না।
তবে, shopt nullglob
উত্তরটি সবচেয়ে ভাল উত্তর!
find
বনাম ব্যবহার করে ls
সমস্যা সমাধানের দুটি ভিন্ন উপায়। find
কোনও মেশিনে সর্বদা উপস্থিত থাকে না তবে ls
সাধারণত হয়
find
সম্ভবত সেই সমস্ত অভিনব বিকল্প নেই ls
।
-maxdepth 1
find
এটি ডিফল্টরূপে করে। এটি কোনও গোপন বাচ্চা ফোল্ডার রয়েছে তা যদি বুঝতে না পারে তবে এটি বিভ্রান্তি তৈরি করতে পারে ls
এবং কোনও পরিস্থিতিতে এটি ব্যবহার করা সুবিধাজনক করে তুলতে পারে , যা ডিফল্টরূপে লুকানো ফাইলগুলির প্রতিবেদন করে না।
এটির জন্য আমার এক লাইনার এখানে।
file_count=$( shopt -s nullglob ; set -- $directory_to_search_inside/* ; echo $#)
set --
আমাদের জন্য প্রস্তুত হচ্ছে ছাড়া কিছু করছেন না $#
, যে দোকানে যে শেল প্রোগ্রাম গৃহীত হয় কমান্ড লাইন আর্গুমেন্ট সংখ্যা
(মন্তব্য করার মতো যথেষ্ট খ্যাতি নেই)
এটি বাজি :
ls -1q some_pattern | wc -l
যদি shopt -s nullglob
সেট হয়ে যায়, এটি সমস্ত নিয়মিত ফাইলের সংখ্যা মুদ্রণ করে , কেবলমাত্র প্যাটার্নের সাথে নয় (সেন্টোস -8 এবং সাইগউইনে পরীক্ষিত)। অন্য অর্থহীন বাগগুলি কী আছে কে জানে ls
?
এটি সঠিক এবং আরও দ্রুত:
shopt -s nullglob; files=(some_pattern); echo ${#files[@]};
এটি প্রত্যাশিত কাজ করে।
0.006
এবং 0.083
সাইগউইনে (যদি এটি যত্ন সহ ব্যবহৃত হয়)।
0.000
এবং 0.003
সাইগউইনে on
শেল ফাংশন ব্যবহার করে আপনি সহজেই এই জাতীয় কমান্ড নির্ধারণ করতে পারেন। এই পদ্ধতিতে কোনও বাহ্যিক প্রোগ্রামের প্রয়োজন হয় না এবং কোনও শিশু প্রক্রিয়া উত্সাহ দেয় না। এটি বিপজ্জনক চেষ্টা করে নাls
পার্সিংয়ের এবং "বিশেষ" অক্ষরগুলি (সাদা স্থান, নিউলাইনস, ব্যাকস্ল্যাশস এবং পরিচালনা করে। এটি কেবল শেল দ্বারা সরবরাহিত ফাইলের নাম সম্প্রসারণ ব্যবস্থার উপর নির্ভর করে। এটি কমপক্ষে sh, বাশ এবং zsh এর সাথে সামঞ্জস্যপূর্ণ।
নীচের লাইনটি একটি ফাংশন সংজ্ঞায়িত করে count
যা এটি ডাকা হয়েছে তার সাথে যুক্তিগুলির সংখ্যা মুদ্রণ করে।
count() { echo $#; }
কেবল এটি পছন্দসই প্যাটার্ন দিয়ে কল করুন:
count log*
ফলাফলটি সঠিক হওয়ার জন্য যখন গ্লোব্বিং প্যাটার্নটির কোনও মিল নেই, শেল বিকল্পটি nullglob
(বা failglob
- যা zsh এর উপর ডিফল্ট আচরণ) সেট করা উচিত যখন সম্প্রসারণ ঘটে। এটি সেট করা যেতে পারে:
shopt -s nullglob # for sh / bash
setopt nullglob # for zsh
আপনি কী গণনা করতে চান তার উপর নির্ভর করে আপনি শেল বিকল্পেও আগ্রহী হতে পারেন dotglob
।
দুর্ভাগ্যক্রমে, কমপক্ষে বাশ দিয়ে, স্থানীয়ভাবে এই বিকল্পগুলি সেট করা সহজ নয়। যদি আপনি তাদের বিশ্বব্যাপী সেট করতে না চান তবে সর্বাধিক সরল সমাধান হ'ল ফাংশনটিকে আরও সংশ্লেষিত পদ্ধতিতে ব্যবহার করা:
( shopt -s nullglob ; shopt -u failglob ; count log* )
আপনি যদি লাইটওয়েট সিনট্যাক্সটি পুনরুদ্ধার করতে চান count log*
, বা আপনি যদি সত্যিই সাবস্কেলের স্প্যানিং এড়াতে চান তবে আপনি এর লাইন ধরে কিছু হ্যাক করতে পারেন:
# sh / bash:
# the alias is expanded before the globbing pattern, so we
# can set required options before the globbing gets expanded,
# and restore them afterwards.
count() {
eval "$_count_saved_shopts"
unset _count_saved_shopts
echo $#
}
alias count='
_count_saved_shopts="$(shopt -p nullglob failglob)"
shopt -s nullglob
shopt -u failglob
count'
বোনাস হিসাবে, এই ফাংশনটি আরও সাধারণভাবে ব্যবহৃত হয়। এই ক্ষেত্রে:
count a* b* # count files which match either a* or b*
count $(jobs -ps) # count stopped jobs (sh / bash)
ফাংশনটিকে স্ক্রিপ্ট ফাইলে রূপান্তর করে (বা সমতুল্য সি প্রোগ্রাম), যা PATH থেকে কলযোগ্য, এটি প্রোগ্রাম find
এবং যেমন xargs
:
find "$FIND_OPTIONS" -exec count {} \+ # count results of a search
আমি এই উত্তরটি অনেক চিন্তাভাবনা দিয়েছি, বিশেষত: পার্স-এলএস স্টাফ দেওয়া হয়নি । প্রথমে আমি চেষ্টা করেছিলাম
<সতর্কবার্তা! কাজ করিনি>
du --inodes --files0-from=<(find . -maxdepth 1 -type f -print0) | awk '{sum+=int($1)}END{print sum}'
</ সতর্কবার্তা! কাজ করিনি>
যা কেবলমাত্র কোনও ফাইলনামের মতো হলে কাজ করে
touch $'w\nlf.aa'
তবে আমি যদি এইরকম কোনও ফাইলনাম তৈরি করি তবে ব্যর্থ হয়েছি
touch $'firstline\n3 and some other\n1\n2\texciting\n86stuff.jpg'
আমি অবশেষে যা নিচে রাখছি তা নিয়ে এসেছি। দ্রষ্টব্য আমি ডিরেক্টরিতে সমস্ত ফাইলের একটি গণনা পাওয়ার চেষ্টা করছিলাম (কোনও সাব-ডিরেক্টরি অন্তর্ভুক্ত নয়)। আমি মনে করি এটি @ ম্যাট এবং @ ড্যান_ইয়ার্ডের উত্তরগুলির পাশাপাশি কমপক্ষে বেশ কয়েকটি প্রয়োজনীয় প্রয়োজনীয়তা যা মোগসি দ্বারা নির্ধারিত হয়েছে (আমি স্মৃতি সম্পর্কে নিশ্চিত নই।) আমি মনে করি @ মোগসির উত্তর সঠিক, তবে আমি সর্বদা পার্সিং থেকে দূরে থাকার চেষ্টা করি ls
যদি না এটি অত্যন্ত নির্দিষ্ট পরিস্থিতি থাকে।
awk -F"\0" '{print NF-1}' < <(find . -maxdepth 1 -type f -print0) | awk '{sum+=$1}END{print sum}'
আরও পঠনযোগ্য:
awk -F"\0" '{print NF-1}' < \
<(find . -maxdepth 1 -type f -print0) | \
awk '{sum+=$1}END{print sum}'
এটি ফাইলগুলির জন্য বিশেষত সন্ধান করছে, শূন্য চরিত্রের সাহায্যে আউটপুটকে সীমিত করে (স্পেস এবং লাইনফিডগুলির সাথে সমস্যা এড়াতে), তারপরে নাল অক্ষরের সংখ্যা গণনা করছে। ফাইলগুলির সংখ্যা নাল অক্ষরের সংখ্যার চেয়ে এক কম হবে, যেহেতু শেষে একটি নাল অক্ষর থাকবে।
ওপির প্রশ্নের উত্তর দেওয়ার জন্য, দুটি বিষয় বিবেচনা করতে হবে
1) পুনরাবৃত্তি অনুসন্ধান:
awk -F"\0" '{print NF-1}' < \
<(find . -maxdepth 1 -type f -name "log*" -print0) | \
awk '{sum+=$1}END{print sum}'
2) পুনরাবৃত্ত অনুসন্ধান। নোট করুন যে -name
প্যারামিটারের ভিতরে যা আছে তার সামান্য ভিন্ন আচরণের জন্য (লুকানো ফাইল ইত্যাদি) পরিবর্তনের প্রয়োজন হতে পারে।
awk -F"\0" '{print NF-1}' < \
<(find . -type f -name "log*" -print0) | \
awk '{sum+=$1}END{print sum}'
এই উত্তরগুলি আমি এই উত্তরে উল্লেখ করেছি এমনগুলির সাথে কীভাবে এই উত্তরগুলির তুলনা করা যায় সে সম্পর্কে কেউ মন্তব্য করতে চাইলে দয়া করে করুন।
দ্রষ্টব্য, এই উত্তরটি পেয়ে আমি এই চিন্তা প্রক্রিয়াটিতে পৌঁছেছি ।
আমি সর্বদা যা করি তা এখানে:
এলএস লগ * | awk 'END {প্রিন্ট এনআর}'
awk 'END{print NR}'
সমতূল্য হওয়া উচিত wc -l
।
ls -1 log* | wc -l
যার অর্থ প্রতি লাইনে একটি ফাইল তালিকাবদ্ধ করুন এবং তারপরে প্যারামিটারের সাথে গণনা লাইনে স্যুইচ করে ওয়ার্ড কাউন্ট কমান্ডে পাইপ করুন।
-l
, যেহেতুstat(2)
প্রতিটি ফাইলের জন্য এটি প্রয়োজন এবং গণনা করার উদ্দেশ্যে কোনও কিছুই যুক্ত হয় না।