Yanıtlar:
İşte GNU find
ve 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
find
Komut hiyerarşisinde tüm dosyaların dizinini yazdırır ve uniq
sadece 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 -print
neden olur find
.
Gizli dosyaları da (adları bir nokta ile başlayan dosyalar) dikkate almak için sh -c
komut 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 --posix
Ve test
tü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
test
ve dir2
(benim cevap bakınız) benim test kurulumunda dizinleri.
test/x1
ve test/x2
aynı zamanda dosyaları gibi ... $1
ve $2
için dizinleri olacak test
ve dizin özleyeceğiz.
Başka find
+ wc
yaklaşı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)
- count
bulunan 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/…