2012-06-21 7 views
17

बैश का उपयोग करके, दुभाषिया शिकायत किए बिना शेल स्क्रिप्ट से निर्देशिका को छोड़कर, किसी फ़ोल्डर में फ़ाइलों की संख्या कैसे प्राप्त हो सकती है?एक चर के रूप में फ़ोल्डर में फ़ाइलों की संख्या कैसे प्राप्त करें?

../1-prefix_blended_fused.jpg: No such file or directory 
ls -l : command not found 
grep ^-: command not found 
wc -l: command not found 

क्रमश:

एक दोस्त की मदद से

, मैं

$files=$(find ../ -maxdepth 1 -type f | sort -n) 
$num=$("ls -l" | "grep ^-" | "wc -l") 

जो कमांड लाइन से रिटर्न की कोशिश की है। ये आदेश कमांड लाइन पर काम करते हैं, लेकिन बैश स्क्रिप्ट के साथ नहीं।

1-pano.jpg जैसे प्रारूपित छवि फ़ाइलों से भरे फ़ाइल को देखते हुए, मैं निर्देशिका में सभी छवियों को पकड़ने के लिए सबसे बड़ी संख्या में फ़ाइल को संसाधित करने के लिए अगली छवि पर काम करने के लिए लेना चाहता हूं।

विसंगति क्यों?

+0

आपके आदेशों के आसपास उद्धरण के साथ क्या है? – sarnold

+0

इसके अलावा, एक चर को असाइन करते समय डॉलर के संकेतों से छुटकारा पाएं; 'फाइल = $ (ढूंढें ...)' और 'num = $ (ls -l ...)'। – chepner

+0

@ कर्नाल्ड, कई स्क्रिप्टिंग ट्यूटोरियल कहते हैं कि निष्पादन ब्लॉक के अंदर रिक्त स्थान एक बुरी चीज है, और जोखिम को कम करने के लिए डबल कोट्स का उपयोग करना है। – Jason

उत्तर

32

उद्धरण त्रुटि संदेश उत्पन्न कर रहे हैं हो जाएगा।

निर्देशिका में फ़ाइलों की एक संख्या प्राप्त करने के लिए:

shopt -s nullglob 
numfiles=(*) 
numfiles=${#numfiles[@]} 

जो एक सरणी बनाता है और फिर उसके तत्वों की गिनती के साथ यह बदल देता है। इसमें फाइलें और निर्देशिकाएं शामिल होंगी, लेकिन डॉटफाइल या . या .. या अन्य बिंदीदार निर्देशिकाएं शामिल नहीं होंगी।

उपयोग nullglob तो एक खाली निर्देशिका 0 के बजाय 1.

इसके बजाय आप find -type f उपयोग कर सकते हैं या आप निर्देशिका गिनती और घटा सकते की गिनती देता है:

# continuing from above 
numdirs=(*/) 
numdirs=${#numdirs[@]} 
((numfiles -= numdirs)) 

इसके अलावा "How can I find the latest (newest, earliest, oldest) file in a directory?"

देखना

आपके पास निष्पादन ब्लॉक के अंदर जितनी चाहें उतनी रिक्त स्थान हो सकती हैं। वे अक्सर पठनीयता में सहायता करते हैं। केवल नकारात्मक पक्ष यह है कि वे फ़ाइल को थोड़ा बड़ा बनाते हैं और प्रारंभिक पार्सिंग (केवल) को धीमा कर सकते हैं। कुछ स्थानों पर रिक्त स्थान होना आवश्यक है कि कर रहे हैं (उदाहरण के लिए चारों ओर [, [[, ], ]] और तुलना में =) और कुछ है कि नहीं करना चाहिए (उदाहरण के लिए एक काम में चारों ओर =

+0

बैश सरणी थोड़ा अधिक है इस तरह का उपयोग !! (जब वे बड़े होते हैं तो धीमे हो जाते हैं) – neam

+0

इसे करने का बहुत बढ़िया तरीका .. .xx –

+0

'numfiles = (*); numfiles = $ {# numfiles [@]} 'एक खाली निर्देशिका पर' 1' – Meisner

1

उद्धरणों से छुटकारा पाएं। खोल उन्हें एक फ़ाइल की तरह व्यवहार कर रहा है, इसलिए यह "ls -l" की तलाश में है।

10

कैसे के बारे में:।

count=$(find .. -maxdepth 1 -type f|wc -l) 
echo $count 
let count=count+1 # Increase by one, for the next file number 
echo $count 

ध्यान दें कि यह समाधान कुशल नहीं है: यह find और wc आदेश के लिए उप गोले spawns, लेकिन यह काम करना चाहिए

+0

यह वही है जो मैंने किया था। इसके अलावा, माइक्रोसॉन्ड में दक्षता चिंता का बहुत अधिक नहीं है क्योंकि यह आदेश लगभग 20-40 मिनट के अंतराल पर चलाया जाएगा। – Jason

+0

बिल्कुल; यदि आप सही ढंग से पाइपलाइनिंग का उपयोग करते हैं, तो भीतरी स्पॉन्स आंतरिक लूप में नहीं होंगे। खैर, वे सभी आंतरिक-लूप असेंबली लाइन का हिस्सा होंगे; लेकिन वे बाधा नहीं होगी। –

2

file_num=$(ls -1 --file-type | grep -v '/$' | wc -l)

01।

यह एक खोज कमांड से थोड़ा हल्का है, और वर्तमान निर्देशिका की सभी फ़ाइलों को गिनती है।

+1

मेरे लिए, 'ls -1 --file-type' रिटर्न' ls: अवैध विकल्प - -'। यदि आप एक विक्रेता-विशिष्ट समाधान प्रदान करने जा रहे हैं, तो कम से कम विक्रेता का जिक्र करें। इसके अलावा, यह symlinks को बाहर नहीं करता है। – ghoti

0

सरल कुशल विधि:

#!/bin/bash 
RES=$(find ${SOURCE} -type f | wc -l) 
+3

क्या आप एक संक्षिप्त स्पष्टीकरण दे सकते हैं कि यह क्यों काम करता है? कोड डंपिंग (आमतौर पर) निराश होती है क्योंकि ओपी पूरी तरह से समझने के लिए सिंटैक्स के बारे में पर्याप्त नहीं जानता कि आप क्या करने की कोशिश कर रहे हैं। – rayryeng

+1

सावधान रहें, यह निर्देशिका में लाइनब्रेक्स के साथ फ़ाइल नाम होने पर यह काम नहीं करता है। –

8
ls -l | grep -v ^d | wc -l 

एक पंक्ति।

+1

यह सार्वभौमिक रूप से सही नहीं है। इस कॉल में अधिकांश अवसरों में "कुल " पंक्ति शामिल होगी (और इस प्रकार एक बहुत अधिक गिनती है, http://stackoverflow.com/questions/7401704/what-is-that-total-in-the-very- पहली पंक्ति के बाद ls-एल)।इसे रोकने के लिए वाइल्डकार्ड जोड़ें: ls -l * | grep -v^डी | wc -1 –

+0

अच्छी तरह से देखा गया, शायद: ls -l | grep -v^डी | grep -v^टी | wc -l तो। – mckenzm

+0

हां, यह ठीक काम करेगा। –

0

स्वीकार्य उत्तर (डेनिस डब्ल्यू द्वारा) पर विस्तार: जब मैंने इस दृष्टिकोण की कोशिश की तो मुझे बैश 4.4.5 में उपनिवेशों के बिना डीआईआर के लिए गलत मायने रखती है।

समस्या यह है कि डिफ़ॉल्ट रूप से nullglob बैश में सेट नहीं है और numdirs=(*/) ग्लोब पैटर्न */ के साथ 1 तत्व सरणी सेट करता है। इसी तरह मुझे संदेह है कि numfiles=(*) में एक खाली फ़ोल्डर के लिए 1 तत्व होगा।

shopt -s nullglob को nullglobbing को अक्षम करने के लिए मेरे लिए समस्या हल करता है। बैश पर डिफॉल्ट रूप से नलग्लोब सेट क्यों नहीं किया गया है, इस पर एक उत्कृष्ट चर्चा के लिए यहां जवाब देखें: Why is nullglob not default?

नोट: मैंने सीधे उत्तर पर टिप्पणी की होगी लेकिन प्रतिष्ठा बिंदुओं की कमी होगी।

संबंधित मुद्दे

 संबंधित मुद्दे