2012-12-05 88 views
12

我正在學習bash腳本並編寫了一個腳本來計算作爲參數提供的目錄中的文件和目錄。我的工作方式對我來說似乎很奇怪,我想知道是否有一種更簡單的方法。使用shell腳本計算文件和目錄

我已經註釋掉了可以正常工作的代碼,但是將其留作比較。我試圖讓for環回工作,而不是使用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

另一評論:我可以告訴你,學習bash的來源已經過時,並沒有顯示良好的做法。 –

+0

在文件名擴展考慮閱讀:http://bash.cyberciti.biz/bash-reference-manual/Filename-Expansion.html – hovanessyan

回答

4

你不是遍歷文件列表中給定的目錄;在$LOCATION之後加/*。你的腳本應該是這樣的:

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

正如指出的羅布麻,只需添加/*將只計算不以.開頭的文件;這樣做,你應該做到以下幾點:

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

中的項目這是腳本中的實際主要問題。 – Jite

+1

這就是我正在尋找的答案!謝謝。這裏的其他解決方案都計算了位置的子目錄的文件和目錄,這些我都不需要。乾杯。 –

+1

好點。也許一個單獨的循環與$ LOCATION /.* ?? ?? –

10

要只是解決您可以使用問題:

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

find會尋找所有文件(-type f)或目錄(-type d)遞歸$LOCATION下;在每種情況下,wc -l都會計算寫入stdout的行數。

但是,如果你想學習,bash腳本可能是一個更好的方法。一些評論:

  • 如果你想尋找的文件/目錄中$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

@AlanSmith,'$ [...]'是不贊成使用的語法,我甚至無法在'man bash'中找到它。現代版本是'$((...))'(儘管它們似乎以相同的方式工作)。對於你的任務,你也可以使用'((++ 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

他正在尋找一種方法來區分dirs和文件的計數 - 這就是爲什麼他的代碼中有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

這顯然是這種特殊情況下最好的方法!正如提到的那樣,它處理所有可能的文件名稱中包含有趣符號的情況,並且對於包含大量文件的目錄(對於使用globbing的bash解決方案來說不是這種情況)也能很好地工作。但有一件事,我的'find'抱怨'-type f'選項後面給出了'-maxdepth 1'。 (另一件事,雙引號在這裏不是必要的,但它從不傷害它們)。 –