Score:4

Count number of files with specific extension(s) for each subdirectory

mx flag

Source: Any directory tree with any number and type of files. Q: How many .jpg or .jpg and .png (for example) are in each subdirectory?

How can I limit the code below for files with 1 or more specific extension(s)? Having trouble inserting the -type f -name "*.jpg*", for example.

for DIR in $(find . -maxdepth 99 -type d)
do
    printf "%10d\t%s\n" $(find ${DIR}|wc -l) "${DIR}" 
done

Desired output:

118   ./aaa
 73   ./aaa/bbb
 16   ./aaa/bbb/ccc

If more than one file types are counted, then their combined total number in each subdirectories should be displayed.

Liso avatar
sd flag
Do you want combine the result of `.jpg` and `.png` ?
Score:4
cn flag

Probably this find|xargs solution will work as you need.

find . -mindepth 1 -maxdepth 99 -type d -print0 | \
   xargs -0 -i bash -c 'printf "%10d\t%s\n" "$(find "$1" -maxdepth 1 -type f -regextype awk -iregex ".*\.(jpg|jpeg|png)" | wc -l)" "$1"' - '{}'

Some explanations:

  • The -mindepth 1 option is added in order to skip the current directory and process only the sub directories.
  • The -print0 provides the output entries with null delimiter, it works together with the -0 option of xargs.
  • The option - "{}" at the end will pass the xargs argument as value of the first positional parameter $1 of the bash command.
  • Within the second find command -iregex means case insensitive regular expression (you could use -regex instead).
user3026965 avatar
mx flag
elegant! is there a easy way to suppress listing those subdirs where the count= 0? (e.g., no files matching the `*\.(jpg|jpeg|png)"`).
pa4080 avatar
cn flag
Hi, @user3026965, the most easiest way to suppress these lines is by adding `| grep -Pv '^\s+0'` at the end of the command. The option `-P` enables the extended regular expressions, `-v` suppress the matched lines and the regex itself means a line which starts `^` with one or more `+` whitespaces `\s` followed by `0`.
Score:3
sd flag

Here's from mine, modified from this answer.

find . -maxdepth 100 -type d -print0 | while read -d '' -r dir; do count=$(find "$dir" -maxdepth 1 -type f \( -name '*.jpg' -o -name '*.png' \) -ls | wc -l); printf "%5d %s\n" "$count" "$dir"; done

Return this on my test directory.

20 .
11 ./level2
3 ./level2/level3

Where the content is:

$ tree -L 3 level1/
level1/
├── 1.png
├── 10.png
├── 11.png
├── 12.png
├── 13.png
├── 14.png
├── 15.png
├── 16.jpg
├── 17.jpg
├── 18.jpg
├── 19.jpg
├── 2.png
├── 20.jpg
├── 3.png
├── 4.png
├── 5.png
├── 6.png
├── 7.png
├── 8.png
├── 9.png
└── level2
    ├── 20.jpg
    ├── 21.jpg
    ├── 22.jpg
    ├── 23.jpg
    ├── 24.jpg
    ├── 25.jpg
    ├── 26.png
    ├── 27.png
    ├── 28.png
    ├── 29.png
    ├── 30.png
    └── level3
        ├── bull_city.png
        ├── man_city.png
        └── newyork_city.png

2 directories, 34 files

Just realized you only need sub directories printed.
find . -mindepth 1 -maxdepth 100 -type d -print0 | while read -d '' -r dir; do count=$(find "$dir" -maxdepth 1 -type f \( -name '*.jpg' -o -name '*.png' \) -ls | wc -l); printf "%5d %s\n" "$count" "$dir"; done

Return this.

11 ./level2
3 ./level2/level3
Score:1
it flag

Find has logical operators like AND, NOT and OR.

To specify more than one extension to search for you need to put the arguments in parentheses, as well as escape the parentheses to avoid them being processed by bash:

find . \( -type f -name "*.jpg" -o -name "*.png" \)
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.