2012-12-05 18 views
12

का उपयोग कर फाइलों और निर्देशिकाओं की गणना करें मैं बैश स्क्रिप्टिंग सीख रहा हूं और निर्देशिका के रूप में दी गई निर्देशिका में फ़ाइलों और निर्देशिकाओं की गणना करने के लिए एक स्क्रिप्ट लिखी है। मेरे पास यह एक तरह से काम कर रहा है जो मेरे लिए अजीब लगता है और सोच रहा हूं कि ऐसा करने का एक आसान तरीका है या नहीं।शैल स्क्रिप्ट

मैंने उस कोड को टिप्पणी की है जो काम करेगा, लेकिन इसे तुलना के रूप में छोड़ दिया। मैं for -loop काम करने की कोशिश कर रहा हूं, इसके बजाय if बयानों का उपयोग करके यह पता लगाने के लिए कि किसी दिए गए स्थान में कोई आइटम फ़ाइल या निर्देशिका है या नहीं।

संपादित: मैं बस बाहर है कि टिप्पणी की कोड दिए गए स्थान की उपनिर्देशिका के साथ-साथ में सभी फ़ाइलों और निर्देशिकाओं में गिना जाता है मिल गया! क्या इसे रोकने के लिए कोई तरीका है और बस दिए गए स्थान की फ़ाइलों और निर्देशिकाओं की गणना करें?

#!/bin/bash 

LOCATION=$1 
FILECOUNT=0 
DIRCOUNT=0 

if [ "$#" -lt "1" ] 
then 
    echo "Usage: ./test2.sh <directory>" 
    exit 0 
fi 

#DIRS=$(find $LOCATION -type d) 
#FILES=$(find $LOCATION -type f) 

#for d in $DIRS 
#do 
# DIRCOUNT=$[$DIRCOUNT+1] 
#done 

#for f in $FILES 
#do 
# FILECOUNT=$[$FILECOUNT+1] 
#done 

for item in $LOCATION 
do 
if [ -f "$item" ] 
    then 
     FILECOUNT=$[$FILECOUNT+1] 
    elif [ -d "$item" ] 
     then 
     DIRCOUNT=$[$DIRCOUNT+1] 
fi 
done 

echo "File count: " $FILECOUNT 
echo "Directory count: " $DIRCOUNT 

किसी कारण for -loop के उत्पादन में, कोई फर्क नहीं पड़ता है जहाँ मैं करने के लिए स्थान इंगित करते हैं, हमेशा रिटर्न के लिए:

File count: 0 , Directory count: 1 
+0

आपका पूरा स्क्रिप्ट टूट गया है। जैसे ही आप झुका रहे हैं, मेरी पहली सलाह है: अधिक उद्धरणों का उपयोग करें! –

+0

एक और टिप्पणी: मैं बता सकता हूं कि बैश सीखने के लिए आपके स्रोत पुराने हैं और अच्छे अभ्यास नहीं दिखाते हैं। –

+0

फ़ाइल नाम विस्तार पर पढ़ने पर विचार करें: http://bash.cyberciti.biz/bash-reference-manual/Filename-Expansion.html – hovanessyan

उत्तर

4

आप फ़ाइलों की सूची से अधिक पुनरावृत्ति नहीं कर रहे हैं अंदर दिया निर्देशिका; $LOCATION के बाद /* जोड़ें। आपकी स्क्रिप्ट की तरह दिखना चाहिए:

... 
for item in $LOCATION/* 
do 
... 

dogbane द्वारा बताया के रूप में, बस /* जोड़ने केवल उन्हीं फ़ाइलों को . से शुरू नहीं होता की गणना होती है; ऐसा करने के लिए, आप करूँ निम्नलिखित: $LOCATION तहत

FILECOUNT=$(find $LOCATION -type f | wc -l) 
DIRCOUNT=$(find $LOCATION -type d | wc -l) 

find सभी फाइलें (-type f) या निर्देशिका के लिए दिखेगा (-type d) रिकर्सिवली:

... 
for item in $LOCATION/* $LOCATION/.* 
do 
... 
+2

में आइटम के लिए स्क्रिप्ट में वास्तविक मुख्य समस्या है। – Jite

+1

यही वह जवाब है जिसे मैं ढूंढ रहा हूं! धन्यवाद। यहां अन्य समाधानों ने सभी स्थान की उप निर्देशिकाओं की फ़ाइलों और निर्देशिकाओं की गणना की, जो मैं नहीं चाहता था। चीयर्स। –

+1

अच्छा बिंदु। शायद $ LOCATION/.* के साथ एक अलग पाश ?? –

10

बस समस्या आप उपयोग कर सकते हैं हल करने के लिए ; wc -l प्रत्येक मामले में stdout को लिखे गए लाइनों की संख्या की गणना करेगा।

हालांकि यदि आप सीखना चाहते हैं, तो बैश स्क्रिप्ट एक बेहतर तरीका हो सकता है। कुछ टिप्पणियां:

  • आप $LOCATION में फ़ाइलें/निर्देशिका देखने के लिए चाहते हैं, तो केवल (नहीं रिकर्सिवली उनके उपनिर्देशिका आदि के तहत), आप for item in $LOCATION/*, जहां *$LOCATION में फ़ाइलें/निर्देशिका की सूची में विस्तार होगा उपयोग कर सकते हैं निर्देशिका। गायब * यही कारण है कि आपकी मूल स्क्रिप्ट 0/1 लौटाती है (क्योंकि $LOCATION निर्देशिका स्वयं ही एकमात्र आइटम गिना जाता है)।
  • आप पहले जांचना चाहेंगे कि $LOCATION वास्तव में [ -d $LOCATION ] के साथ एक निर्देशिका है।
  • अंकगणितीय अभिव्यक्तियों के लिए, $((...)) का उपयोग करें, उदाहरण के लिए FILECOUNT=$((FILECOUNT + 1))
  • यदि आप सभी फाइलें/निर्देशिकाओं को बार-बार खोजना चाहते हैं, तो आप find को लूप के साथ जोड़ सकते हैं।

उदाहरण:

find $LOCATION | while read item; do 
    # use $item here... 
done 
+0

हां, $ LOCATION/* कोड पूरी तरह से काम किया। क्यों $ ((...)) $ [] के बजाय? प्रदर्शन से संबंधित? –

+0

@Alanmith, '$ [...] 'को सिंटैक्स को हटा दिया गया है, मैं इसे' मैन बाश 'में भी नहीं ढूंढ सकता। आधुनिक संस्करण '$ ((...)) है (हालांकि वे एक ही तरीके से काम करते हैं)। अपने कार्य के लिए आप केवल '((++ FILECOUNT)) का उपयोग कर सकते हैं। Http://stackoverflow.com/questions/2188199/bash-double-or-single-bracket-parentheses-curly-braces देखें। –

+0

ठीक है, बहुत अच्छी जानकारी, धन्यवाद। –

2

... am wondering if there is a simpler way of doing it.

आप ऐसा कहते हैं;)

वैकल्पिक रूप से,

find /path/to/directory | wc -l 

वर्तमान निर्देशिका के लिए करने के लिए अपनी स्क्रिप्ट को कम करते हैं:

find . | wc -l 
+0

नोट: यह फ़ाइल के रूप में '.' की गणना भी करता है। तो केवल दो नियमित फाइलों के साथ जो मुझे लगता है कि आप गिनना चाहते हैं, यह '3' प्रिंट करेगा। – Jite

+0

वह डीआईआर और फाइलों की गिनती को अलग करने का एक तरीका ढूंढ रहा है - यही कारण है कि उसके कोड में 2 काउंटर हैं। आपका खोज कुल प्रकार की गिनती देता है, फ़ाइल प्रकारों के बीच अंतर नहीं करता है। – hovanessyan

1

उपयोग

find $LOCATION -maxdepth 1 -type f | wc -l 

फ़ाइलों की गिनती के लिए, और

find $LOCATION -maxdepth 1 -type d | wc -l 

गिनती निर्देशिका

12

उपयोग find जिन्हें आप नीचे के लिए। यह समाधान रिक्त स्थान, न्यूलाइन और डॉटफाइल के साथ फ़ाइल नामों को सही तरीके से गिना जाएगा।

FILECOUNT="$(find . -type f -maxdepth 1 -printf x | wc -c)" 
DIRCOUNT="$(find . -type d -maxdepth 1 -printf x | wc -c)" 

ध्यान दें कि DIRCOUNT वर्तमान निर्देशिका (.) भी शामिल है। आप इस नहीं करना चाहते हैं, घटाना यदि फ़ाइल नामों में रिक्तियां होने वाला 1.

((DIRCOUNT--)) # to exclude the current directory 
+0

यह स्पष्ट रूप से इस विशेष मामले में सबसे अच्छी संभव विधि है! जैसा कि कुत्ते का उल्लेख किया गया है, यह उन फ़ाइलों के सभी संभावित मामलों को संभालता है जिनमें उनके नाम पर मजाकिया प्रतीक होते हैं, और निर्देशिकाओं के साथ अच्छी तरह से काम करते हैं जिनमें बहुत सारी फ़ाइलें होती हैं (जो ग्लोबिंग का उपयोग करके बैश समाधान के मामले में नहीं है)। एक बात, हालांकि, 'टाइप प्रकार' विकल्प के बाद 'maxdepth 1'' के बारे में मेरी 'ढूंढ' शिकायत की गई है। (एक और बात, डबल कोट्स यहां जरूरी नहीं हैं, लेकिन इन्हें कभी भी उपयोग करने में दर्द नहीं होता है)। –

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