1

I want to get a list with all the directories that contains more than 20,000 files/subdirectories.

For example:

Folder A
|_ Folder A1
  |_ Folder A11
    |_ 25,000 files
  |_ 15,000 files
|_ Folder A2
  |_ 21,000 files
|_ 10 files

I want to get the following list:

Folder A11
Folder A2

How can I do that?

STF
  • 113

1 Answers1

1

The number of names in a directory may be counted using set -- *. The count is then found in $#.

With find, you may execute the set command and test the value of $# in a short in-line shell script:

find . -type d -exec sh -c '
    for dirpath do
        set -- "$dirpath"/*
        [ "$#" -gt 20000 ] && printf "%s\n" "$dirpath"
    done' sh {} +

The inline sh -c script will get batches of found directory pathnames as arguments. The script iterates over a batch of these pathnames and expands the * glob in each. If the resulting list contains strictly more than 20000 strings, the directory pathname is outputted using printf.

To also count hidden names, you may want to switch to calling the bash shell with its dotglob shell option set:

find . -type d -exec bash -O dotglob -c '
    for dirpath do
        set -- "$dirpath"/*
        [ "$#" -gt 20000 ] && printf "%s\n" "$dirpath"
    done' bash {} +

Note that if you want to do something to these directories, you'd be best served if you do that as part of the inline script above (rather than, say, try to parse the output of the find command):

find . -type d -exec bash -O dotglob -c '
    for dirpath do
        set -- "$dirpath"/*
        [ "$#" -gt 20000 ] || continue
    # Process "$dirpath" here

done' bash {} +

Kusalananda
  • 333,661
  • What should I write in dirpath? my dir path? – STF Jan 24 '23 at 11:07
  • 1
    @STF The commands, as given, will operate on the current directory (and it will recursively descend into subdirectories). If you need to point the find command elsewhere, then change the . after find to the desired top-level directory. Do not modify dirpath in the script, it's a variable that the script uses and its values will be provided by find. – Kusalananda Jan 24 '23 at 11:25
  • ♦ I tried the script in one line and got: find . -type d -exec sh -c 'for dirpath do set -- "$dirpath"/* [ "$#" -gt 20000 ] && printf "%s\n" "$dirpath" done' bash {} + bash: -c: line 1: syntax error: unexpected end of file bash: -c: line 1: syntax error: unexpected end of file bash: -c: line 1: syntax error: unexpected end of file bash: -c: line 1: syntax error: unexpected end of file – STF Jan 24 '23 at 11:28
  • 1
    @STF Yes, that is expected. You will have to add a few semi-colons if you want to fold it into a single line: find . -type d -exec sh -c 'for dirpath do set -- "$dirpath"/*; [ "$#" -gt 20000 ] && printf "%s\n" "$dirpath"; done' sh {} + – Kusalananda Jan 24 '23 at 11:31