Ответы:
Здесь совершенно другой подход, основанный на GNU findи uniq. Это намного быстрее и намного проще для процессора, чем ответы, основанные на выполнении команды оболочки, которая считает файлы для каждого найденного каталога.
find . -type f -printf '%h\n' | sort | uniq -d
Команда findпечатает каталог всех файлов в иерархии и uniqотображает только те каталоги, которые появляются как минимум дважды.
-printf '%h\0' | sort -z | uniq -zd | xargs -r0 ...
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
Это позволит найти все имена в текущем каталоге или под ним, а затем отфильтровать все имена, которые не являются именами каталогов.
Остальные имена каталогов будут переданы этому короткому сценарию:
c=0
for n in "$1"/*; do
[ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done
[ "$c" -ge 2 ]
Этот скрипт будет подсчитывать количество обычных файлов (пропуская символические ссылки) в каталоге, указанном в качестве первого аргумента командной строки (from find). Последняя команда в скрипте - это проверка, чтобы увидеть, было ли количество 2 или больше. Результатом этого теста является возвращаемое значение (состояние выхода) скрипта.
Если проверка прошла успешно, -printбудет findраспечатан путь к каталогу.
Чтобы также рассмотреть скрытые файлы (файлы, имена которых начинаются с точки), измените sh -cсценарий со слов
for n in "$1"/*; do
в
for n in "$1"/* "$1"/.*; do
Тестирование:
$ 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
[ "" -ge 2 ]как это допустимый тест.
dash, bash --posixи testвсе отображают сообщение об ошибке и выходят с 2 (т.е. «Произошла ошибка»)
kshработала как sh. Скорректирую сразу. Спасибо, что тыкаешь в меня! :-)
[ -f ... ]разыменовываются символические ссылки. Вы должны добавить тест, чтобы устранить их, так как вопрос указывает, что должны учитываться только обычные файлы.
С помощью ответа Жиля о SU и его реверсе и некоторой модификации, вот что вам нужно.
find . -type d -exec sh -c 'set -- "$1"/*;X=0;
for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print
Дерево каталогов.
.
├── 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
Результат:
./test
./test/dir1
./test/dir2/dirb
testи те dir2каталоги , в моей тестовой конфигурации (см мой ответ).
test/x1и в test/x2виде файлов ... $1и $2будет каталогами для test, и каталог будет пропущен.
Еще один find+ wcподход:
find path/currdir -maxdepth 1 -type d ! -empty ! -path "path/currdir" \
-exec sh -c 'count=$(find "$1" -maxdepth 1 -type f | wc -l); [ $count -ge 2 ]' _ {} \; -print
path/currdir - путь к вашей текущей директории
-maxdepth 1- учитывать только прямые дочерние подпапки
! -empty - игнорировать пустые подпапки
! -path "path/currdir" - игнорировать текущий путь к каталогу
count=$(find "$1" -maxdepth 1 -type f | wc -l)- countприсваивается количество файлов для каждой найденной подпапки
[ $count -ge 2 ] ... -print - напечатать имя / путь к подпапке, содержащей 2 или более обычных файла
find. В этом случае, потому что GNUfindбудет искажать имена каталогов, в которых есть символы, которые нельзя распечатать в текущей локали (например, «ä» в локали C). См. Также unix.stackexchange.com/questions/321697/…