-2

I need to write a Linux script, which will count the number of subfolders with at least one letter containing "c" in the name of these subfolders, which is in the current folder?

I have following solution:

#!/bin/bash

Count the number of subfolders in the current directory

that contain the letter "c" in their name

count=0

Loop through all items in the current directory

for folder in */; do

Check if the folder name contains the letter "c"

if [[ "$folder" == c ]]; then # Increment the counter ((count++)) fi done

Print the result

echo "Number of subfolders containing the letter 'c': $count"

Is this right? Is there any other way to solve the same problem?

2 Answers2

2

You can try to find the c right when listing the directories:

ls -bd *c*/ | wc -l

The -b helps if any of the directories has a newline in its name - we don't want to count it twice.

To include hidden directories, you need to also add .*c* or set the dotglob shell option (shopt -s dotglob).

choroba
  • 10,313
2

I don't see anything wrong with what you've done - however it could be simpler. In particular, you don't need the [[ "$folder" == *c* ]] test if you use a glob pattern that only matches names containing c from the get-go:

count=0

shopt -s nullglob for folder in c/; do ((count++)) done

Note that if you go that route you need to set the nullglob option, otherwise you will get an apparent count of 1 when there are no matches (because the unexpanded pattern *c*/ gets passed to the loop).

But there are ways that don't require the explicit shell loop at all. If you want to count only non-hidden directories at the top-level of the current directory, then in bash you could place the matching directories in an array, then print the number of elements:

shopt -s nullglob
dirs=( *c*/ )
printf "Number of subfolders containing the letter 'c': %c\n" "${#dirs[@]}"

If you want to include hidden (dot) directories, set the dotglob shell option as well, i.e. shopt -s nullglob dotglob.

To count recursively, I'd suggest using the find command, e.g.

count=$(find . -type d -name '*c*' -printf x | wc -c)

where x is an arbitrary single byte character. You could use -printf '\n' with wc -l if you prefer. Note that this includes hidden directories by default so you would need to exclude them explicitly, e.g. -name '*c*' ! -name '.*'.1

With zsh you could use an anonymous shell function to count glob matches directly, e.g.

# non-recursive, exclude hidden dirs
() { printf "Number of subfolders containing the letter 'c': %d\n" $# } *c*(/N)

non-recursive, include hidden dirs

() { printf "Number of subfolders containing the letter 'c': %d\n" $# } c(/ND)

recursive, include hidden dirs

() { printf "Number of subfolders containing the letter 'c': %d\n" $# } */c*(/ND)

where the glob qualifiers /ND select directories only, and apply the nullglob and dotglob flags.

See also Count total number of files in particular directory with specific extension.


1. You could of course use find non-recursively as well, by adding -maxdepth 1

steeldriver
  • 142,475