1

Problem Statement: To list down the count of files within a directory. Note: A directory may either contain a sub-directory or files but not both. Need to list count of files directory wise. Here is the piece of code.

#!/usr/bin/sh 
directory_navigate()
{   
    path=$1
    cd $path
    dir_count=`ls -l|grep '^d'|wc -l`
    if [ $dir_count -gt 0 ]
    then
        for dir in `ls`
        do
            sub_path="$path/$dir"
            directory_navigate $subpath
        done
    else    
        sub_path=`pwd`
        file_count $sub_path 
        return
    fi
}   

file_count ()
{
    path=$1
    cd $path
    count=`ls|wc -l`
    echo "Count of files in $path is $count"
    return
}

main()
{
    filepath=/var/prod/data/extract/tbill
    directory_navigate $filepath
    return 
}

main 

This throws the following error: recursion too deep

user3004
  • 19
  • 2

1 Answers1

2

Use globstar . In bash do

shopt -s globstar
count=0
for name in /basefolder/**
do
[ -f "$name" ] && (( count++ ))
done
echo "Total files : $count"

A simpler approach as suggested in the comment is

find /basefolder/ -type f -printfc | wc -c

Here, the catch is that we don't have to parse( and are not parsing, we just want to count) the files, if we require to parse the files for more complex requirements, then below are some reasons for not using find.

  • Using find requires that you need to null-delimit each file (ie use -print0).
  • Furthermore, you need to use while - read -r -d ' ' combination to parse each file.
  • In short, not worth the effort.

Edit: If you want to have a directory-wise file-count listing, do below

#!/bin/bash
shopt -s globstar
for name in ~/Documents/so/**
do
if [ -d "$name" ]
then
  count="$(find "$name" -type f -printf c | wc -c)"
  echo "Total files in $name : $count"
fi
done
sjsam
  • 21,411
  • 5
  • 55
  • 102
  • As a side note, globstar is only available since bash 4.0. Some OS like MacOS won't have it by default and will need to upgrade their shell. – Aserre Dec 19 '16 at 14:02
  • @Aserre : Good note, I am aware of this. The op mentioned `unix` in question, so hopefully he has bash version > 4.0 – sjsam Dec 19 '16 at 14:03
  • MacOS is Unix-based :) – Aserre Dec 19 '16 at 14:07
  • 1
    How about using `find . -type f -printf c | wc -c`? Doesn't need a lot of effort – user000001 Dec 19 '16 at 14:07
  • @user000001 : That won't deal with non-standard files like `AnewlineB`. In fact those files are rare but they do exists on some machines. – sjsam Dec 19 '16 at 14:09
  • @sjsam: Yes it can handle it. It prints a single character for each file regardless of the filename. Of course there is the problem that some `find` implementations may not have the `printf` option... – user000001 Dec 19 '16 at 14:10
  • @Aserre : Again i agree, but users on `Mac` generally tag `Mac` in the questions. – sjsam Dec 19 '16 at 14:11
  • @user000001 : It won't. `find` unlike `ls` will not add random characters in place of newlines, indeed that is one speciality of `find`. – sjsam Dec 19 '16 at 14:13
  • @sjsam: That sounds really strange. Post the output of `find . -type f -printf c` on your console. You should see the character `c` printed several times, regardless of the filenames contained inside the current directory – user000001 Dec 19 '16 at 14:15
  • 1
    @user000001 : I am sorry, I overlooked the `-printf c` in your comment. Yes it does what it is supposed to do.. :) – sjsam Dec 19 '16 at 14:20
  • hi, the requirement here is to find the count of files directory wise. So find function doesn't fulfill this requirement and also printf option does not work – user3004 Dec 20 '16 at 08:43