Odpowiedzi:
Oto zupełnie inne podejście oparte na GNU find
i uniq
. Jest to o wiele szybsze i bardziej przyjazne dla procesora niż odpowiedzi oparte na wykonywaniu polecenia powłoki, które zlicza pliki dla każdego znalezionego katalogu.
find . -type f -printf '%h\n' | sort | uniq -d
find
Komenda drukuje katalog wszystkich plików w hierarchii i uniq
wyświetla tylko te katalogi, które pojawiają się co najmniej dwa razy.
-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
Spowoduje to znalezienie wszystkich nazw w bieżącym katalogu lub pod nim, a następnie odfiltrowanie wszystkich nazw, które nie są nazwami katalogów.
Pozostałe nazwy katalogów zostaną podane temu krótkiemu skryptowi:
c=0
for n in "$1"/*; do
[ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done
[ "$c" -ge 2 ]
Ten skrypt policzy liczbę zwykłych plików (pomijając dowiązania symboliczne) w katalogu podanym jako pierwszy argument wiersza poleceń (od find
). Ostatnie polecenie w skrypcie jest testem sprawdzającym, czy liczba wynosiła 2 lub więcej. Wynikiem tego testu jest wartość zwracana (status wyjścia) skryptu.
Jeśli test się powiedzie, -print
spowoduje find
wydrukowanie ścieżki do katalogu.
Aby uwzględnić również ukryte pliki (pliki, których nazwy zaczynają się od kropki), zmień sh -c
skrypt w powiedzeniu
for n in "$1"/*; do
do
for n in "$1"/* "$1"/.*; do
Testowanie:
$ 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 ]
jest to prawidłowy test.
dash
, bash --posix
i test
wszystkie wyświetlają komunikat o błędzie i wychodzą z 2 (tzn. „Wystąpił błąd”)
ksh
działa jako mas sh
. Poprawi się natychmiast. Dzięki za szturchanie mnie! :-)
[ -f ... ]
wyklucza dowiązania symboliczne. Powinieneś dodać test, aby je wyeliminować, ponieważ pytanie określa, że należy liczyć tylko zwykłe pliki.
Z pomocą odpowiedzi Gillesa na SU i jej odwrotnej kolejności oraz modyfikacji, oto czego potrzebujesz.
find . -type d -exec sh -c 'set -- "$1"/*;X=0;
for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print
Drzewo katalogów.
.
├── 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
Wynik:
./test
./test/dir1
./test/dir2/dirb
test
i dir2
katalogi w mojej konfiguracji testowej (patrz moja odpowiedź).
test/x1
i test/x2
jako pliki również ... $1
i $2
będą katalogami dla test
, a katalog zostanie pominięty.
Inne podejście 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
- ścieżka do twojego bieżącego katalogu
-maxdepth 1
- rozważ tylko bezpośrednie podfoldery podrzędne
! -empty
- ignoruj puste podfoldery
! -path "path/currdir"
- zignoruj bieżącą ścieżkę katalogu
count=$(find "$1" -maxdepth 1 -type f | wc -l)
- count
jest przypisany z liczbą plików dla każdego znalezionego podfolderu
[ $count -ge 2 ] ... -print
- wydrukuj nazwę / ścieżkę podfolderu zawierającą 2 lub więcej zwykłych plików
find
. W tym przypadku, ponieważ GNUfind
będzie zmieniać nazwy katalogów, które mają znaki, których nie można wydrukować w bieżących ustawieniach narodowych (takich jak „ä” w ustawieniach regionalnych C). Zobacz także unix.stackexchange.com/questions/321697/…