Directories with two or more files

Here is a completely different approach based on GNU find and uniq. This is much faster and much CPU-friendly than answers based on executing a shell command that counts files for each directory found.

find . -type f -printf '%h\n' | sort | uniq -d

The find command prints the directory of all files in the hierarchy and uniq only displays the directories that appear at least twice.


find . -type d \
    -exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' \
    -print

This will find all names in or under the current directory and then filter out all names that are not names of directories.

The remaining directory names will be given to this short script:

c=0
for n in "$1"/*; do
    [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done

[ "$c" -ge 2 ]

This script will count the number of regular files (skipping symbolic links) in the directory given as the first command line argument (from find). The last command in the script is a test to see if the count was 2 or greater. The result of this test is the return value (exit status) of the script.

If the test succeeded, -print will cause find to print out the path to the directory.

To also consider hidden files (files whose names begins with a dot), change the sh -c script from saying

for n in "$1"/*; do

to

for n in "$1"/* "$1"/.*; do

Testing:

$ tree
.
`-- test
    |-- a
    |-- dir1
    |   |-- a
    |   |-- b
    |   `-- c
    `-- dir2
        |-- dira
        |-- dirb
        |   |-- file-1
        |   `-- file-2
        `-- dirc

6 directories, 6 files

$ find . -type d -exec sh -c 'c=0; for n in "$1"/*; do [ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 )); done; [ "$c" -ge 2 ]' sh {} ';' -print
./test/dir1
./test/dir2/dirb

With the help of Gilles's answer on SU and its reverse and some modification, here what you need.

find . -type d -exec sh -c 'set -- "$1"/*;X=0; 
    for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print

Directory tree.

.
├── test
│   ├── dir1
│   │   ├── a
│   │   ├── b
│   │   └── c
│   ├── dir2
│   │   ├── dira
│   │   │   └── a file\012with\012multiple\012line
│   │   ├── dirb
│   │   │   ├── file-1
│   │   │   └── file-2
│   │   └── dirc
│   ├── diraa
│   ├── dirbb
│   ├── dircc
│   └── x
│   └── x1
│   └── x2
└── test2
    ├── dir3
    └── dir4

Result:

./test
./test/dir1
./test/dir2/dirb

Tags:

Find

Files