Abs
Abs

Reputation: 57996

Finding the number of files in a directory for all directories in pwd

I am trying to list all directories and place its number of files next to it.

I can find the total number of files ls -lR | grep .*.mp3 | wc -l. But how can I get an output like this:

dir1 34 
dir2 15 
dir3 2 
...

I don't mind writing to a text file or CSV to get this information if its not possible to get it on screen.

Thank you all for any help on this.

Upvotes: 4

Views: 5611

Answers (5)

Peter Lyons
Peter Lyons

Reputation: 146164

This seems to work assuming you are in a directory where some subdirectories may contain mp3 files. It omits the top level directory. It will list the directories in order by largest number of contained mp3 files.

find . -mindepth 2 -name \*.mp3 -print0| xargs -0 -n 1 dirname | sort | uniq -c | sort -r | awk '{print $2 "," $1}'

I updated this with print0 to handle filenames with spaces and other tricky characters and to print output suitable for CSV.

Upvotes: 7

guzzo
guzzo

Reputation: 1

Here's yet another way to even handle file names containing unusual (but legal) characters, such as newlines, ...:

# count .mp3 files (using GNU find)
find . -xdev -type f -iname "*.mp3" -print0 | tr -dc '\0' | wc -c

# list directories with number of .mp3 files
find "$(pwd -P)" -xdev -depth -type d -exec bash -c '
  for ((i=1; i<=$#; i++ )); do
    d="${@:i:1}"
    mp3s="$(find "${d}" -xdev -type f -iname "*.mp3" -print0 | tr -dc "${0}" | wc -c )"
    [[ $mp3s -gt 0 ]] && printf "%s\n" "${d}, ${mp3s// /}"
  done
' "'\\0'" '{}' +

Upvotes: 0

Dimitre Radoulov
Dimitre Radoulov

Reputation: 28010

With Perl:

perl -MFile::Find -le'
  find { 
    wanted => sub {
      return unless /\.mp3$/i;
      ++$_{$File::Find::dir};
      }
    }, ".";
  print "$_,$_{$_}" for 
    sort { 
      $_{$b} <=> $_{$a} 
      } keys %_;
  '

Upvotes: 0

Wrikken
Wrikken

Reputation: 70540

find . -type f -iname '*.mp3' -printf "%h\n" | uniq -c

Or, if order (dir-> count instead of count-> dir) is really important to you:

find . -type f -iname '*.mp3' -printf "%h\n" | uniq -c | awk '{print $2" "$1}'

Upvotes: 4

Jon
Jon

Reputation: 16726

There's probably much better ways, but this seems to work.

Put this in a shell script:

#!/bin/sh
for f in *
do
  if [ -d "$f" ]
  then
      cd "$f"
      c=`ls -l *.mp3 2>/dev/null | wc -l`
      if test $c -gt 0
      then
          echo "$f $c"
      fi
      cd ..
  fi
done

Upvotes: 3

Related Questions