উত্তর:
এই সহজ ওয়ানলাইনারটি কেবল বাশ নয়, যে কোনও শেলটিতে কাজ করা উচিত:
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
ব্যাখ্যা:
-Ulsএন্ট্রিগুলি বাছাই না করার কারণ , এর জন্য এটি মেমরির সম্পূর্ণ ডিরেক্টরি তালিকা লোড করার প্রয়োজন হয় না-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বলে tellsfindx
একটি পুনরাবৃত্তি অনুসন্ধানের জন্য, এটি করুন:
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)প্রতিটি ফাইলের জন্য এটি প্রয়োজন এবং গণনা করার উদ্দেশ্যে কোনও কিছুই যুক্ত হয় না।