`Ls -l` मेरे से अधिक फ़ाइलों की गणना क्यों करता है?


25

जाहिरा तौर पर मैं गिनती नहीं कर सकता। मुझे लगता है कि इसमें तीन फाइलें हैं/media

$ tree /media
/media
├── foo
├── onex
└── zanna
3 directories, 0 files

हालांकि, ls -l12 पाता है।

$ ls -l /media
total 12
drwxr-xr-x  2 root root 4096 Jul 31 20:57 foo
drwxrwxr-x  2 root root 4096 Jun 26 06:36 onex
drwxr-x---+ 2 root root 4096 Aug  7 21:17 zanna

और, अगर मैं करता हूं तो ls -laमुझे उपरोक्त के अलावा केवल .और केवल मिलता ..है, लेकिन गिनती हैtotal 20

स्पष्टीकरण क्या है?

जवाबों:


33

12जैसा कि आप देख फ़ाइलों की संख्या नहीं है, लेकिन डिस्क ब्लॉक की संख्या का सेवन किया।

से info coreutils 'ls invocation':

 For each directory that is listed, preface the files with a line
 `total BLOCKS', where BLOCKS is the total disk allocation for all
 files in that directory.  The block size currently defaults to 1024
 bytes, but this can be overridden (*note Block size::).  The
 BLOCKS computed counts each hard link separately; this is arguably
 a deficiency.

कुल से चला जाता 12है 20जब आप उपयोग करते हैंls -lals -l दो अतिरिक्त निर्देशिकाओं की गिनती कर रहे हैं, तो इसके बजाय करते हैं: .और ..। आप प्रत्येक (खाली) निर्देशिका के लिए चार डिस्क ब्लॉक का उपयोग कर रहे हैं, इसलिए आपका कुल 3 × 4 से 5 × 4 तक चला जाता है (सभी संभावना में, आप प्रत्येक निर्देशिका के लिए 4096 बाइट्स के एक डिस्क ब्लॉक का उपयोग कर रहे हैं ; जैसा कि infoपृष्ठ इंगित करता है, उपयोगिता डिस्क प्रारूप की जांच नहीं करती है, लेकिन 1024जब तक अन्यथा निर्देश नहीं दिया जाता है तब तक ब्लॉक आकार मानती है ।)

यदि आप केवल फाइलों की संख्या प्राप्त करना चाहते हैं, तो आप कुछ इस तरह की कोशिश कर सकते हैं

ls | wc -l

13
ls | wc -lफ़ाइल नाम में एक नई पंक्ति के साथ फ़ाइलें हैं, तो विफल हो जाएगा। यह अधिक लचीला है:find . -mindepth 1 -maxdepth 1 -printf . | wc -c
फ़्लिम

20
"यदि फ़ाइल के नाम में एक नई पंक्ति है" ... कंपकंपी
पेटा

8
जैसा man lsकि आप बताएंगे, आप नियंत्रण चार्ट से -bबच सकते हैं (उन्हें बच जाता है) या -q(उन्हें छोड़ देता है)। तो गिनती के लिए, ls -1q | wc -lगैर-छिपी हुई फ़ाइलों को दिखाने के लिए सुरक्षित और सटीक है। ls -1qA | wc -lछिपे हुए फ़ाइलें (लेकिन गिनती करने के लिए .और ..)। मैं -1इसके बजाय उपयोग कर रहा हूं -lक्योंकि यह तेज होना चाहिए।
ओली

18

user4556274 पहले से ही उत्तर है क्यों । मेरा जवाब केवल के लिए अतिरिक्त जानकारी प्रदान करने के लिए कार्य करता है है कि कैसे ठीक से फ़ाइलें गिनती करने के लिए।

यूनिक्स समुदाय में आम सहमति यह है कि आउटपुट को पार्स करना lsएक बहुत ही बुरा विचार है , क्योंकि फ़ाइल नाम में नियंत्रण वर्ण या छिपे हुए वर्ण हो सकते हैं। उदाहरण के लिए, फ़ाइल नाम में एक नए वर्ण के कारण, हमने ls | wc -lबताया कि आउटपुट में 5 पंक्तियाँ हैं ls(जिसमें यह है), लेकिन वास्तव में निर्देशिका में केवल 4 फाइलें हैं।

$> touch  FILE$'\n'NAME                                                       
$> ls                                                                         
file1.txt  file2.txt  file3.txt  FILE?NAME
$> ls | wc -l
5

विधि # 1: उपयोगिता खोजें

findआदेश, जो आम तौर पर काम कर रहे फ़ाइल नाम पार्स करने के लिए प्रयोग किया जाता है, हमें यहाँ मुद्रण द्वारा मदद कर सकते हैं आइनोड संख्या । यह एक निर्देशिका या एक फ़ाइल हो, इसमें केवल एक अद्वितीय इनोड संख्या है। इस प्रकार, का उपयोग करते हुए -printf "%i\n"और को छोड़कर .के माध्यम से -not -name "."हम फ़ाइलों का एक सटीक गणना कर सकते हैं। (नोट करें कि -maxdepth 1उप-श्रेणियों में पुनरावर्ती अवरोही को रोकने के लिए उपयोग करें )

$> find  -maxdepth 1 -not -name "." -print                                    
./file2.txt
./file1.txt
./FILE?NAME
./file3.txt
$> find  -maxdepth 1 -not -name "." -printf "%i\n" | wc -l                    
4

विधि # 2: ग्लोबस्टार

सरल, त्वरित और अधिकतर पोर्टेबल तरीका:

$ set -- * 
$ echo $#
228

setकमांड का उपयोग शेल (जैसे $<INTEGER>चर echo $1) के स्थितीय मापदंडों को सेट करने के लिए किया जाता है । यह अक्सर /bin/shकमी सरणियों की सीमा के आसपास काम करने के लिए उपयोग किया जाता है । एक संस्करण जो अतिरिक्त जांच करता है, वह यूनिक्स और लिनक्स पर गिल के जवाब में पाया जा सकता है ।

गोले का समर्थन करने वाले गोले में, जैसे bash, हम उपयोग कर सकते हैं

items=( dir/* )
echo ${#items[@]}

जैसा कि टिप्पणियों में स्टीलड्राइवर द्वारा प्रस्तावित किया गया था

findविधि के समान चाल wcऔर ग्लोबस्टार का उपयोग statप्रति लाइन इनोड संख्या की गणना करने के लिए किया जा सकता है :

$> LC_ALL=C stat ./* --printf "%i\n" | wc -l                                          
4

एक वैकल्पिक दृष्टिकोण forलूप में वाइल्डकार्ड का उपयोग करना है । (ध्यान दें, यह परीक्षण यह परीक्षण करने के लिए एक अलग निर्देशिका का उपयोग करता है कि क्या यह दृष्टिकोण उपनिर्देशिका में उतरता है, जो ऐसा नहीं करता है - 16 मेरे में मदों की सत्यापित संख्या है ~/bin)

$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1                                
16

विधि # 3: अन्य भाषाओं / दुभाषियों

पायथन समस्याग्रस्त फ़ाइल नाम के साथ मेरे os.listdir()कार्य को दी गई सूची की लंबाई को मुद्रित करने के माध्यम से भी निपट सकता है (जो गैर-पुनरावर्ती है, और केवल तर्क के रूप में दी गई निर्देशिका में आइटम सूचीबद्ध करेगा)।

$> python -c "import os ; print os.listdir('.')"                              
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$>  python -c "import os ; print(len(os.listdir('.')))"                    
4

यह भी देखें


2
बैश में, एक अन्य विकल्प एक सरणी का उपयोग करना होगा उदाहरण के लिए items=( dir/* ); echo ${#items[@]}( shopt -s dotglobछिपी फ़ाइलों को शामिल करने के लिए)।
स्टीलड्राइवर

1
इनकोड संख्याओं को प्रिंट करने से हार्डलिंक को फ़िल्टर करना आसान हो जाता है, यदि वांछित हो find | sort -u | wc -l
पीटर कॉर्ड्स

@steeldriver: मुझे लगता है कि बैश-ऐरे विधि के तेज होने की संभावना नहीं है। यदि आप चाहते हैं कि यह पुनरावर्ती हो, तो आपको उपयोग करने की आवश्यकता है items=( dir/** )(साथ shopt -s globstar), लेकिन बैश रेडीडर से अतिरिक्त मेटाडेटा का लाभ नहीं उठाता है, इसलिए यह प्रत्येक निर्देशिका प्रविष्टि को देखने के लिए आँकड़े देता है कि क्या यह एक निर्देशिका है। कई फाइलसिस्टम डायरेक्टरी प्रविष्टि में फाइलाइप को स्टोर करते हैं, इसलिए रीडडीयर इनकोड्स को एक्सेस किए बिना इसे वापस कर सकता है। (उदाहरण के लिए नवीनतम गैर-डिफ़ॉल्ट XFS में यह है, और मुझे लगता है कि ext4 ने इसे लंबे समय तक रखा है।) यदि आप straceपाते हैं, तो आपको statस्ट्रैपिंग बैश की तुलना में बहुत कम सिस्टम कॉल दिखाई देंगे ।
पीटर कॉर्ड्स

2
सिर्फ उपयोग क्यों नहीं print(len(os.listdir('.')))? टाइप करने के लिए कम अक्षर और डबल-अंडरस्कोर विशेषता तक पहुँचने से भी बचता है।
edwinksl

1
@edwinksl ने संपादित किया, thx
सर्गी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.