Yanıtlar:
İşte GNU findve dayalı tamamen farklı bir yaklaşım uniq. Bu, bulunan her dizin için dosyaları sayan bir kabuk komutunun yürütülmesine dayalı cevaplardan çok daha hızlı ve CPU dostudur.
find . -type f -printf '%h\n' | sort | uniq -d
findKomut hiyerarşisinde tüm dosyaların dizinini yazdırır ve uniqsadece iki kez en az görünen dizinleri görüntüler.
-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
Bu işlem, geçerli dizindeki veya altındaki tüm adları bulur ve ardından dizin adı olmayan tüm adları filtreler.
Kalan dizin adları bu kısa komut dosyasına verilecektir:
c=0
for n in "$1"/*; do
[ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done
[ "$c" -ge 2 ]
Bu komut dosyası, ilk komut satırı bağımsız değişkeni (from find) olarak verilen dizindeki normal dosya sayısını (sembolik bağlantıları atlayarak) sayar . Koddaki son komut, sayının 2 veya daha yüksek olup olmadığını görmek için bir sınamadır. Bu testin sonucu, komut dosyasının dönüş değeridir (çıkış durumu).
Sınama başarılı olursa, dizinin yolunun yazdırılmasına -printneden olur find.
Gizli dosyaları da (adları bir nokta ile başlayan dosyalar) dikkate almak için sh -ckomut dosyasını
for n in "$1"/*; do
için
for n in "$1"/* "$1"/.*; do
Test yapmak:
$ 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 ]Geçerli bir sınama olduğundan bir dizinde normal dosya yoksa hata yoktur .
dash, bash --posixVe testtüm ekran 2 ile bir hata mesajı ve çıkış (yani "Bir hata oluştu")
kshçalıştığı bir sistemi test ediyordum sh. Hemen değişiklik yapacaktır. Bana alay ettiğin için teşekkürler! :-)
[ -f ... ]sembolik bağlantıları dereferences. Soru yalnızca normal dosyaların sayılması gerektiğini belirttiğinden bunları ortadan kaldırmak için bir test eklemelisiniz.
Yardımıyla Gilles cevabı üzerine SU bunun tersinin ve bazı modifikasyon, ihtiyacınız ne burada.
find . -type d -exec sh -c 'set -- "$1"/*;X=0;
for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print
Dizin ağacı.
.
├── 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
Sonuç:
./test
./test/dir1
./test/dir2/dirb
testve dir2(benim cevap bakınız) benim test kurulumunda dizinleri.
test/x1ve test/x2aynı zamanda dosyaları gibi ... $1ve $2için dizinleri olacak testve dizin özleyeceğiz.
Başka find+ wcyaklaşımı:
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 - geçerli dizininize giden yol
-maxdepth 1- yalnızca doğrudan alt alt klasörleri göz önünde bulundurun
! -empty - boş alt klasörleri yoksay
! -path "path/currdir" - geçerli dizin yolunu yoksay
count=$(find "$1" -maxdepth 1 -type f | wc -l)- countbulunan her alt klasör için dosya sayısı atanır
[ $count -ge 2 ] ... -print - 2 veya daha fazla normal dosya içeren alt klasör adı / yolu yazdır
find. Bu durumda, GNUfind, geçerli yerel ayarda yazdırılamayan karakterlere sahip dizinlerin adlarını değiştirir (C yerel ayarındaki "ä" gibi). Ayrıca bkz. Unix.stackexchange.com/questions/321697/…