-3

The task is: Output when running the file will be the number of subdirectories (counting all subdirectories in the tree) in the entered directory.

I know how to recursive a dir using -r but how can i count all these number in a shell script file?

2 Answers2

4

To count all the directories including hidden ones in a tree rooted at the current directory . either

find . -type d -printf '\n' | wc -l

or

find . -type d -printf x | wc -c

(you can substitute any single character in place of x: if you choose a character that is special to the shell, make sure to quote or escape it). Using printf '\n' | wc -l or printf x | wc -c instead of passing a list of filenames to wc -l will ensure the count is correct even if there are directories whose names contain newlines.

Both commands include the starting directory . in the count - if you want to strictly count subdirectories then either subtract 1 or add -mindepth 1

find . -mindepth 1 -type d -printf '\n' | wc -l

or use ! -name . to exclude the . directory explicitly.

If you want to exclude hidden directories (including possible non-hidden subdirectories of hidden ones), then prune them ex.

find -mindepth 1 -type d \( -name '.*' -prune -o -printf x \) | wc -c

Alternatively, using the shell's recursive globbing to traverse the tree. Using zsh for example

dirs=( **/(ND/) )
print $#dirs

where (ND/) are glob qualifiers that make **/ match only directories and include hidden ("Dot") ones - omit the D if you want to count non-hidden directories only.

You can do something similar in bash:

shopt -s nullglob dotglob globstar
set -f -- **/
printf '%d\n' "$#"

however unlike zsh's / qualifier, the **/ glob pattern matches anything that looks like a directory - including symbolic links to directories.

steeldriver
  • 143,099
2

Try running ls -l -R | grep -c ^d in your terminal from the directory you want to know how many are inside of.

*** edit *** Use the below to scan with a variable path prompted to the user.

#!/bin/bash
echo "Please enter path to scan:"
read path
ls -l -R $path | grep -c ^d
Roxana
  • 86
  • 7
  • That exactly what im looking for – Lê Quốc Khánh Aug 28 '21 at 02:31
  • But how can i set custom path to folder? – Lê Quốc Khánh Aug 28 '21 at 02:35
  • You can add the path the command like such ls -l -R /usr/share/themes | grep -c ^d . You can add a variable like ls -l -R $path | grep -c ^d and have $path as a variable input to your script. – Roxana Aug 28 '21 at 02:46
  • Thank you so much – Lê Quốc Khánh Aug 28 '21 at 02:56
  • 1
    In general, parsing the output of ls is a bad idea. I would not encourage anyone. See https://unix.stackexchange.com/questions/128985/why-not-parse-ls-and-what-to-do-instead – sourav c. Aug 28 '21 at 03:06
  • I edited my answer above to show the variable. Sourav isn't wrong about avoid parsing LS but since you AREN'T looking for file names, rather counting folders, it doesn't matter. it's a simple and clean solution. – Roxana Aug 28 '21 at 03:13
  • 2
    @Roxanna It will still present a problem, believe non-interactive mode uses literal as quoting style, that would mean, e.i., 'folder'$'\n''d' will give false positive, think any other quoting style will do. –  Aug 28 '21 at 08:15