2012-01-11 8 views
2

私は基本的にやって2つの異なるスクリプトを持っていながら、同じ:現在のディレクトリ内のサブディレクトリをカウント:bashの声明

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'オプションを省略すると、サブディレクトリもカウントされます。 –

+0

@chorobaは正解ですが、一般にファイルを数えるには、 'count = $(find -printf x | wc -c)'をお勧めします。 – l0b0

答えて

3

は、Cに割り当て、すなわちサブシェルで、|後に起こります。親シェル内の変数をサブシェルから変更することはできません。 ところで、逆引用符とexprの代わりにlet c++を使用してみませんか?

+1

ありがとうございます - それは、サブシェルで起こるか、この場合のみですか? 私はabotuがC++になることを知らなかった - 私はbashスクリプトの初心者です – Alex

+0

いいえ、それは一般的な動作です。 2番目のコマンドでは、新しいサブシェルを作成しませんでした。変数が値を保持するようにプロセス置換を使用しました。 –

+0

bashでは、パイプライン内の任意のシェルコマンド(つまり、 '|'の前に*または*)がサブシェルで実行されます。他のいくつかのシェルは少し異なります。詳細については、[BashFAQ#024](http://mywiki.wooledge.org/BashFAQ/024)を参照してください。 –

1

私は、私はこれらの2つのコマンドのいずれかを使用するサブディレクトリをカウントする必要がある場合:

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" 

ここでハック方法です:

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

はおそらく上記のいずれかでnullglobdotglobを使用したいと思うでしょう。詳細については、BashFAQ/004を参照してください。

サブローの問題に関しては、チョロバが正しいです。