Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Why does the following scripts give a count of 0 instead of giving the count of files present in the directory?

#!/bin/bash
cd /root/Jamshed/script
count=0
ls -lrt > all_files
cat all_files | while read dir
do  
    count=$(($count + 1))
done
echo $count;
share|improve this question

5 Answers 5

It is giving the count as zero because you are increment count within a subshell. As such, the changes made to the variable are lost.

Instead say:

while read -r dir
do  
    count=$(($count + 1))
done < all_files

to achieve the desired result.

That said, parsing ls is never recommended.

share|improve this answer

You can use an array to hold the filenames and examine the array size:

files=( /root/Jamshed/script/* )
echo "${#files[@]}"

If you want all files recursively:

shopt -s globstar nullglob
files=( /root/Jamshed/script/** )
echo "${#files[@]}"
share|improve this answer

You can do it without parsing ls output or using wc as follows:

cd /root/Jamshed/script
count=0
shopt -s nullglob
for file in * .*[!.]*;do
    count=$(($count+1))
done
echo $count

Explanation

The glob pattern * will match all file and directory names not starting with a . and the glob pattern .*[!.]* will match all file and directory names whose name starts with a . and contains at least one non-. character (to avoid counting the special directories . and ..).

share|improve this answer
1  
That would avoid counting ... and ..... as well. Note that the standard syntax is [!.], not [^.]. Note that in an empty directory, it would return 2. –  Stéphane Chazelas Feb 16 at 17:46

Your script works fine in ksh, you can also change the first line (on Linux the ksh package must have been installed).
#!/bin/ksh ksh doen not use subshells in a loop.

share|improve this answer

Instead of using bash process substitution you may - from bash 4.2 on - use shopt -s lastpipe to avoid the subshell issue (variable assignment in child process is not visible in the parent shell).

(Yet another way to avoid the subshell issue is to use exec and redirect stdin from a file or heredoc).

If you insist on using ls, use ls -1Artb.

# file version
set +f
shopt -s nullglob dotglob
count=0
printf '%s\000' * > all_files
while IFS="" read -r -d "" file; do
   test -z "$file" && continue
   count=$(($count + 1))
   #printf '%s\n' "$count: $file"
done < all_files
echo "$count"

# process substitution version
set +f
shopt -s nullglob dotglob
count=0
while IFS="" read -r -d "" file; do
   test -z "$file" && continue
   count=$(($count + 1))
   #printf '%s\n' "$count: $file"
done < <(printf '%s\000' *)
echo "$count"
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.