Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

For the purpose of testing, I'd like count how many images files are inside a directory, separating each image file type by file extension (jpg="yes". This because later it will be useful for another script that will execute an action on each file extension). Can I use something like the following for only JPEG files?

count=`ls -1 *.jpg 2>/dev/null | wc -l`
if [ $count != 0 ]
echo jpg files found: $count ; jpg="yes"

Considering file extensions jpg, png, bmp, raw and others, should I use a while cycle to do this?

share|improve this question
up vote 6 down vote accepted

I'd suggest a different approach, avoiding the possible word-splitting issues of ls


shopt -s nullglob

for ext in jpg png gif; do 
  files=( *."$ext" )
  printf 'number of %s files: %d\n' "$ext" "${#files[@]}"

  # now we can loop over all the files having the current extension
  for f in "${files[@]}"; do
    # anything else you like with these files


You can loop over the files array with any other commands you want to perform on the files of each particular extension.

share|improve this answer
@1_CR oops thank you - must have brace expansions on the brain! will correct above – steeldriver Jul 26 '14 at 21:37

My approach would be:

  1. List all files in the directory
  2. Extract their extension
  3. Sort the result
  4. Count the occurrences of each extension

Sort of like this:

ls | awk -F . '{print $NF}' | sort | uniq -c | awk '{print $2,$1}'
share|improve this answer
mhmh... later should I filter each extension found for do an action for it? – watchmansky Jul 26 '14 at 19:24
It depends on what you want to do in the end. Can you give more information? – groxxda Jul 26 '14 at 19:25
My goal: a script that process each extension file (only image file) changing the size from input user data. So, I start from how many jpg files there're, next png, etc. – watchmansky Jul 26 '14 at 19:27
steeldrivers solution may be more appropriate then. – groxxda Jul 26 '14 at 19:30

Maybe it can get shorter

exts=( *.jpg *.png *.gif ); printf "There are ${#exts[@]}" extensions;
share|improve this answer

Anything involving ls is likely to produce unexpected results with special chars (space and other symbols). Any bashism (like arrays) isn't portable. Anything involving while read is usually slow.

On the other hand, find is VERY flexible (lots of options to filter), it has [at least] two syntax which are fail safe for special chars... and It scales well on large directory.

For this example, I have used -iname to match both upper and lower case extension name. I have also restricted the -maxdepth 1 to respect your question's "in current directory". Rather than counting the number of lines, where filenames could include CR/LF, -print0 will print a NULL byte at the end of each filename... so | tr -d -c "\000" | wc -l is accurately counting files (NULL bytes!).

extensions="jpg png gif"
for ext in $extensions; do
  c=$(find . -maxdepth 1 -iname "*.$ext" -print0 | tr -d -c "\000" | wc -c)
  if [ $c -gt 0 ]; then
    echo "Found $c  *.$ext files"

    find . -maxdepth 1 -iname "*.$ext" -print0 | xargs -0 -r -n1 DOSOMETHINGHERE
    # or #  find . -maxdepth 1 -iname "*.$ext" -exec "ls" "-l" "{}" ";"

P.S. -print0 | tr -d -c "\000" | wc -c can be replaced with -printf "\000" | wc -c or even -printf '\n' | wc -l.

share|improve this answer
find -type f | sed -e 's/.*\.//' | sort | uniq -c
share|improve this answer
Don't forget a starting directory with find. Also, it can help future readers of these answers if you give a brief explanation of your solution (in case they would like to modify it for a slightly different case). – Jeff Schaller Oct 22 '15 at 16:04
How well does this solution deal with path names containing spaces? Newlines? – dhag Oct 22 '15 at 17:37
find defaults to the current directory, which is how I use this. I don't think God intended filenames to have spaces in them, but this works fine for that case. If you have newlines, then you deserve all you get. I thought about an explanation but decided it would make the answer too long, I think simplicity is what matters. 99% of the cases in 1% of the time. This is probably Version 7 compatible. – Neik Oct 22 '15 at 21:22

Your Answer


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.