How it works...

This script relies on the associative array statarray. This array is indexed by the type of file: PDF, ASCII, and so on. Each index holds the count for that type of file. It is defined by the declare -A statarray command.

The script then consists of two loops: a while loop, that processes the output from the find command, and a for loop, that iterates through the indices of the statarray variable and generates output.

The while loop syntax looks like this:

while read line; 
do something 
done < filename 

For this script, we use the output of the find command instead of a file as input to while.

The (find $path -type f -print) command is equivalent to a filename, but it substitutes the filename with a subprocess output.

Note that the first < is for input redirection and the second < is for converting the subprocess output to a filename. Also, there is a space between these two so the shell won't interpret it as the << operator.

The find command uses the -typef option to return a list of files under the subdirectory defined in $path. The filenames are read one line at a time by the read command. When the read command receives an EOF (End of File), it returns a fail and the while command exits.

Within the while loop, the file command is used to determine a file's type. The -b option is used to display the file type without the name.

The file command provides more details than we need, such as image encoding and resolution (in the case of an image file). The details are comma-separated, as in the following example:

    $ file a.out -b
    ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
    dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not
    stripped

We need to extract only ELF 32-bit LSB executable from the previous details. Hence, we use the -d, option to specify , as the delimiter and -f1 to select the first field.

<(find $path -type f -print) is equivalent to a filename, but it substitutes the filename with a subprocess output. Note that the first < is for input redirection and the second < is for converting the subprocess output to a filename. Also, there is a space between these two so that the shell won't interpret it as the << operator.

In Bash 3.x and higher, we have a new operator <<< that lets us use a string output as an input file. Using this operator, we can write the done line of the loop, as follows:

    done <<< "`find $path -type f -print`"

${!statarray[@]} returns the list of array indexes.