2012-01-11 83 views
2

我有2個不同的腳本做基本相同:在當前目錄計數子目錄:的bash while語句

c=0 

ls -l | grep "^d" | while read zeile 
do 
    c=`expr $c + 1` 
    echo $c 
done 

echo "Subdirs: $c" 

c=0 

while read zeile 
do 
    c=`expr $c + 1` 
    echo $c 
done < <(ls -l | grep "^d") 

echo "Subdirs: $c" 

我的問題是,在第一個版本,「 c「在while循環結束後似乎失去了它的價值。

輸出

1)

1 
2 
3 
Subdirs: 0 

2)

1 
2 
3 
Subdirs: 3 

你們誰能給我解釋一下,爲什麼發生這種情況?

預先感謝 亞歷

+0

或者,您也可以使用'find。 -maxdepth 1 -type d | wc -l'來獲得你的計數(雖然它也會計算當前目錄)。省略'-maxdepth 1'選項以統計子目錄。 – 2012-01-11 15:19:58

+0

@choroba有正確的答案,但一般來說,我會推薦計數文件'count = $(find。-printf x | wc -c)' - 與任何*文件一起使用。 – l0b0 2012-01-12 15:36:28

回答

3

在第一種情況中,分配到c |後會發生,即,在一個子shell。您不能從子shell中更改父shell中的變量。 順便說一句,爲什麼你不使用let c++而不是反引號和expr?

+1

謝謝 - 這是否意味着,在|之後的所有內容發生在一個子shell中,或只在這種情況下? 我不知道abotu讓c + + - 我是一個初學者在bash腳本 – Alex 2012-01-11 14:53:34

+0

沒有多數民衆贊成的一般行爲。在你的第二個命令中,你沒有創建一個新的子shell。您使用流程替代,以便變量保留它的值。 – 2012-01-11 15:30:37

+0

在bash中,管道中任何地方的任何shell命令(即在*之後的*或*之後)都將在子shell中執行。其他一些shell有些不同,詳情參見[BashFAQ#024](http://mywiki.wooledge.org/BashFAQ/024)。 – 2012-01-11 16:14:02

1

如果非要算子目錄,那麼我會使用這兩個命令之一:

find . -regex ".\{2,\}" -maxdepth 1 -type d | wc -l 
ls -l | grep "^d" | wc -l 
0

should not use ls in that way

您應該使用for循環和glob遍歷文件或目錄。

for f in * 
do 
    if [[ -d $f ]] 
    then 
     ((c++)) 
    fi 
done 
echo "Subdirs: $c" 

for f in */ 
do 
    ((c++)) 
done 
echo "Subdirs: $c" 

這裏有一個hackish的方式:

arr=(*/); echo "Subdirs: ${#arr[@]}" 

你可能會想使用nullglobdotglob與上述任何一項。有關更多信息,請參閱BashFAQ/004

Choroba在子外殼問題上是正確的。