ডিরেক্টরিতে ফাইল গণনা করার জন্য ডাব্লুসিপি-তে পাইপিংয়ের আরও একটি সুসংগত বিকল্প আছে কি?


12

আমি যদি করি তবে আমি ls -1 target_dir | wc -lএকটি ডিরেক্টরিতে ফাইলের একটি গণনা পাই। আমি এটি কিছুটা কষ্টকর মনে করি। আরও কি মার্জিত বা সংযোগ উপায় আছে?


2
Wc তে পাইপ দেওয়ার সময় আপনার "-1" লাগবে না।
স্টিভ

lsইতিমধ্যে মোট গণনা দেয়, তাহলে কিভাবে ls -l | head -1? যদি আপনি আরও কিছু সংক্ষিপ্ত চান তবে এটি একটি উপাধি করুন।
ড্যানিয়েল ওয়াগনার

2
@ ড্যানিয়েলওয়াগনার "মোট: এনএনএন" আউটপুট ls -lফাইলগুলির মোট আকার নয়, ফাইলের সংখ্যা নির্দেশ করে।
ডেভিড রিচারবি

2
মনে রাখবেন যে ls | wc -lকোনও ফাইলের নামের মধ্যে নতুন লাইনে থাকা থাকলে আপনাকে ভুল গণনা দেবে।
চিপনার

এটি ফাইল-সিস্টেমের উপর নির্ভর করে এবং ডিরেক্টরিগুলিকে ডিরেক্টরিতে + 2 গণনা করে। উত্তরে 2 টি অতিরিক্ত (যেমন এটি নিজেরাই গণনা করে এবং এর পিতামাতা)। stat -c %h .হিসাবে একই তথ্য দেয়ls -ld . | cut -d" " -f 2
Ctrl-Alt-delor

উত্তর:


12

ধরে নেওয়া বাশ 4+ (যা উবুন্টুর কোনও সমর্থিত সংস্করণ রয়েছে):

num_files() (
    shopt -s nullglob
    cd -P -- "${1-.}" || return
    set -- *
    echo "$#"
)

এটি হিসাবে কল করুন num_files [dir]diralচ্ছিক, অন্যথায় এটি বর্তমান ডিরেক্টরি ব্যবহার করে। আপনার আসল সংস্করণ লুকানো ফাইল গণনা করে না, তাই এটিও করে না। যদি আপনি এটি চান, shopt -s dotglobআগে set -- *

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

num_files() (
    local count=0

    shopt -s nullglob
    cd -P -- "${1-.}" || return
    for file in *; do
        [[ -f $file ]] && let count++
    done
    echo "$count"
)

আপনার যদি জিএনইউ খুঁজে পাওয়া যায় তবে এর মতো কিছু হ'ল একটি বিকল্পও রয়েছে (লক্ষ্য করুন এটিতে লুকানো ফাইল রয়েছে যা আপনার আসল কমান্ডটি করেনি):

num_files() {
    find "${1-.}" -maxdepth 1 -type f -printf x | wc -c
}

( -typeআপনি -xtypeযদি নিয়মিত ফাইলগুলিতে সিমলিঙ্কগুলিও গণনা করতে চান তবে পরিবর্তন করুন )।


setখুব বেশি ফাইল থাকলে ব্যর্থ হবেন না ? আমি মনে করি xargsসাধারণ ক্ষেত্রে সেই কাজটি করার জন্য আপনাকে হয়ত কিছু সংখ্যক কোড ব্যবহার করতে হবে।
l0b0

1
এছাড়াও shopt -s dotglobআপনি যদি ফাইলগুলি .গণনা করতে চান তবে
ডিজিটাল ট্রমা

1
@ l0b0 আমি মনে করি না যে setএই পরিস্থিতিতেগুলি ব্যর্থ হবে, যেহেতু আমরা আসলে এটি করছি না exec। বুদ্ধিমানভাবে, আমার সিস্টেমে, getconf ARG_MAX262144 ফলন হয়, তবে আমি যদি তা করি তবে test_arg_max() { set -- {1..262145}; echo $#; }; test_arg_maxতা খুশিতে 262145 জবাব দেয়
কোজিরো

@ ডেভিডরিচার্বি পসিক্স -maxdepthনয়।
ক্রিস ডাউন

4
@ মিশেলমার্টিনিজ সুস্পষ্ট কোড লেখা সঠিক কোড লেখার বিকল্প নয়।
ক্রিস ডাউন

3

f=(target_dir/*);echo ${#f[*]}

নামে ফাঁকা স্থান, নিউলাইন ইত্যাদির সাথে ফাইলের জন্য সঠিকভাবে কাজ করে।


আপনি কিছু প্রসঙ্গ সরবরাহ করতে পারেন? এটি কি বাশ স্ক্রিপ্টে যাওয়া উচিত?
কোডেকবয়

এটা পারে। আপনি এটি সরাসরি শেলতেও রাখতে পারেন। এই সংস্করণ ধরে নিয়েছে আপনি বর্তমান ডিরেক্টরিটি চান; আমি এটি সম্পাদনা করেছি যাতে এটি আপনার প্রশ্নের নিকটবর্তী হয়। মূলত এটি ডিরেক্টরিতে সমস্ত ফাইল ধারণকারী শেল অ্যারে ভেরিয়েবল তৈরি করে, তারপরে সেই অ্যারের গণনা মুদ্রণ করে। বাশ, ksh, zsh, ইত্যাদি - এর সাথে যে কোনও শেলটিতে কাজ করা উচিত - তবে সম্ভবত প্লে sh / ছাই / ড্যাশ নয়।
অ্যারন ডেভিস

2

lsমাল্টি-কলামগুলি কেবলমাত্র যদি এটি টার্মিনালে সরাসরি আউটপুট করে, আপনি "-1" বিকল্পটি সরাতে পারেন, আপনি wc"-l" বিকল্পটি সরাতে পারেন , কেবলমাত্র প্রথম মানটি পড়তে পারেন (অলস সমাধান, লেজুয়াল প্রমাণগুলির জন্য ব্যবহার না করা, অপরাধমূলক তদন্ত, মিশন সমালোচনা, কৌশলগত অপশন ..)।

ls target | wc 

5
এটি নিউলাইনযুক্ত ফাইলের নামগুলির জন্য ব্যর্থ।
l0b0

@ এমমানুয়েল আপনাকে wcএমনকি তুচ্ছ মামলায় ফাইলের সংখ্যা পেতে আপনার ফলাফলটি বিশ্লেষণ করতে হবে, তবে এটি কীভাবে সমাধান হবে?
l0b0

@ এমমানুয়েল এটি ব্যর্থ হতে পারে যদি targetএমন কোনও গ্লোব হয় যা প্রসারিত হওয়ার সাথে সাথে হাইফেন দিয়ে শুরু হওয়া কিছু জিনিস অন্তর্ভুক্ত থাকে। উদাহরণস্বরূপ, একটি নতুন ডিরেক্টরি তৈরি করুন, এটিতে প্রবেশ করুন এবং করুন touch -- {1,2,3,-a}.txt && ls *|wc(এনবি: rm -- *.txtএই ফাইলগুলি মুছতে ব্যবহার করুন ))
ডেভিড রিচার্বি

মানে wc -l? অন্যথায় আপনি lsআউটপুট এর নিউলাইন, শব্দ এবং বাইট গণনা পাবেন । ডেভিড রিচার্বি এটাই বলেছিলেন: আপনাকে আবার এটি বিশ্লেষণ করতে হবে।
এরিক

@ এরিক আমি wcকোন যুক্তি ছাড়াই আপনার তর্ক করার দরকার নেই যদি আপনার মস্তিষ্ক জেনে থাকে যে প্রথম যুক্তিটি নিউলাইন।
এমমানুয়েল

2

যদি এটি পরস্পরের সাথে সংযুক্ত থাকে (তাদের নামগুলিতে নতুন লাইনের সাথে ফাইলগুলি পরিচালনা করার সময় সঠিক নির্ভুলতার চেয়ে বরং), আমি কেবলমাত্র ("লাইন গণনা") এর সাথে আলিয়াস wc -lকরার পরামর্শ দিই lc:

$ alias lc='wc -l'
$ ls target_dir|lc

অন্যরা যেমন উল্লেখ করেছে, আপনার কোনও -1বিকল্পের দরকার নেই ls, যেহেতু lsপাইপে লেখার সময় এটি স্বয়ংক্রিয় হয়। (যদি না আপনি lsসর্বদা কলাম মোড ব্যবহার না করে থাকেন I've আমি এটি আগে দেখেছি, তবে খুব বেশিবার নয়))

একটি lcউপাধি সাধারণভাবে বেশ কার্যকর, এবং এই প্রশ্নের জন্য, আপনি যদি "বর্তমান ডিরেক্টরি গণনা করুন" কেসটি দেখুন তবে আপনি ls|lcযতটা পারছেন ততটুকু পরস্পর সম্পর্কিত।


2

এখন পর্যন্ত হারুনের একমাত্র পন্থা আপনার নিজের চেয়ে বেশি সংযোগযুক্ত। আপনার পদ্ধতির আরও সঠিক সংস্করণটি দেখতে পাবেন:

ls -aR1q | grep -Ecv '^\./|/$|^$'

ডিরেক্টরিগুলি নয় - সমস্ত ফাইলকে পুনরাবৃত্তভাবে তালিকাবদ্ধ করে - ডিরেক্টরিগুলি নয় - প্রিন্টযোগ্য অক্ষরগুলি প্রতিস্থাপনের জন্য প্রয়োজনীয় শেল গ্লোবগুলি ব্যবহার করে বর্তমান ডিরেক্টরিতে নীচে .ডটফাইলগুলি অন্তর্ভুক্ত রয়েছে। গ্রেপ কোনও অভিভাবক ডিরেক্টরি তালিকা বা .. অথবা * / অথবা ফাঁকা লাইনগুলি ফিল্টার করে - সুতরাং প্রতি ফাইলের জন্য কেবল একটি লাইন থাকতে হবে - যার মধ্যে গ্রেপ আপনাকে ফিরিয়ে দেয় তার মোট গণনা। আপনি যদি চাইল্ড ডিরেক্টরিগুলি অন্তর্ভুক্ত করতে চান তবে করুন:

ls -aR1q | grep -Ecv '^\.{1,2}/|^$'

-Rযদি আপনি পুনরাবৃত্তির ফলাফল না চান তবে উভয় ক্ষেত্রেই সরিয়ে ফেলুন ।


1
আমি এ জাতীয় জিনিসটি পছন্দ করতে পছন্দ করি find। আপনি যদি কেবল একটি গণনা চান তবে এটি কাজ করা উচিত: find -mindepth 1 -maxdepth 1 -printf '\n'|wc -l(পুনরাবৃত্তির ফলাফল পেতে গভীরতা নিয়ন্ত্রণগুলি সরিয়ে ফেলুন)।
অ্যারন ডেভিস 21

@ অ্যারোন ডেভিস - এটি আসলে কাজ করে না। এই ফাইলের যে কোনও একটিতে একটি নতুন লাইন রাখুন এবং নিজের জন্য দেখুন। এছাড়াও একই জিনিসটি বহনযোগ্যভাবে করার জন্য: আপনি find . \! -name . -prune | wc -lএখনও কার্যকর করেন না অবশ্যই।
মাইকজার্ভ

1
আমি অনুসরণ করি না - printfনির্দেশনাটি একটি ধ্রুব স্ট্রিং (একটি নতুন লাইন) মুদ্রণ করে যা কোনওভাবেই ফাইলের নাম অন্তর্ভুক্ত করে না, সুতরাং ফলাফলগুলি কোনও অদ্ভুত ফাইলের নামের চেয়ে পৃথক। অবশ্যই এই কৌশলটি কোনওটিই findসমর্থন করে না যা printfঅবশ্যই সমর্থন করে না ।
অ্যারন ডেভিস

@ অ্যারোন ডেভিস - ওহ, সত্য আমি ধরে নিলাম ফাইলের নাম অন্তর্ভুক্ত ছিল। এটি অবশ্যই বহনযোগ্যভাবে করা যেতে পারে, অবশ্যই:find .//. \!. -name . -prune | grep -c '^\.//\.'
মাইকজার্ভ

উজ্জ্বল! /কেবলমাত্র অন্য একটি চরিত্র যা ফাইলের নামগুলিতে উপস্থিত হতে পারে না, .//.অনুক্রমটি প্রতিটি ফাইলের জন্য ঠিক একবারে উপস্থিত হওয়ার নিশ্চয়তা দেওয়া হয়েছে, তাই না? একটি দম্পতি যদিও প্রশ্ন - কেন .//., এবং কেন -prune? এটি কখন থেকে পৃথক হবে find . \! -name . | grep -c '^\.'? (আমি ধরেছি .আপনার \!.মধ্যে একটি টাইপো রয়েছে))
অ্যারন ডেভিস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.