Alex
Alex

Reputation: 25

bash while statement

I have 2 different scripts doing basically the same: counting the subdirectories in the current directory:

c=0

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

echo "Subdirs: $c"

and

c=0

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

echo "Subdirs: $c"

My Problem is, that in the first version, "c" seems to lose it's value after the while-loop has finished.

The outputs

1)

1
2
3
Subdirs: 0

2)

1
2
3
Subdirs: 3

Can anyone of you explain to me, why this is happening?

Thanks in advance Alex

Upvotes: 2

Views: 251

Answers (3)

Dennis Williamson
Dennis Williamson

Reputation: 359965

You should not use ls in that way.

You should use a for loop and a glob to iterate over files or directories.

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

or

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

Here's a hackish way:

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

You will probably want to use nullglob and dotglob with any of the above. See BashFAQ/004 for more information.

Choroba is correct regarding the subshell issue.

Upvotes: 0

anubhava
anubhava

Reputation: 785008

If I have to count sub directories then I would use either of these 2 commands:

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

Upvotes: 1

choroba
choroba

Reputation: 241828

In the first case, the assignment to c happens after the |, i.e. in a subshell. You cannot change a variable in a parent shell from a subshell. BTW, why do not you use let c++ instead of backquotes and expr?

Upvotes: 3

Related Questions