Jawaban:
Berikut adalah pendekatan yang sama sekali berbeda berdasarkan pada GNU find
dan uniq
. Ini jauh lebih cepat dan lebih ramah CPU daripada jawaban berdasarkan mengeksekusi perintah shell yang menghitung file untuk setiap direktori yang ditemukan.
find . -type f -printf '%h\n' | sort | uniq -d
The find
perintah mencetak direktori dari semua file dalam hirarki dan uniq
hanya menampilkan direktori yang muncul setidaknya dua kali.
-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
Ini akan menemukan semua nama di atau di bawah direktori saat ini dan kemudian menyaring semua nama yang bukan nama direktori.
Nama direktori yang tersisa akan diberikan ke skrip pendek ini:
c=0
for n in "$1"/*; do
[ -f "$n" ] && [ ! -h "$n" ] && c=$(( c + 1 ))
done
[ "$c" -ge 2 ]
Script ini akan menghitung jumlah file biasa (melewatkan tautan simbolik) di direktori yang diberikan sebagai argumen baris perintah pertama (dari find
). Perintah terakhir dalam skrip adalah tes untuk melihat apakah hitungannya 2 atau lebih besar. Hasil tes ini adalah nilai balik (status keluar) dari skrip.
Jika tes berhasil, -print
akan menyebabkan find
untuk mencetak jalur ke direktori.
Untuk juga mempertimbangkan file tersembunyi (file yang namanya dimulai dengan titik), ubah sh -c
skrip agar tidak mengatakan
for n in "$1"/*; do
untuk
for n in "$1"/* "$1"/.*; do
Pengujian:
$ 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 ]
ini adalah tes yang valid.
dash
, bash --posix
dan test
semua menampilkan pesan kesalahan dan keluar dengan 2 (yaitu "Terjadi kesalahan")
ksh
berjalan seperti mas sh
. Akan segera diubah. Terima kasih telah menyodok saya! :-)
[ -f ... ]
tautan simbolik dereferensi. Anda harus menambahkan tes untuk menghilangkannya karena pertanyaan menentukan bahwa hanya file biasa yang harus dihitung.
Dengan bantuan jawaban Gilles pada SU dan kebalikannya dan beberapa modifikasi, inilah yang Anda butuhkan.
find . -type d -exec sh -c 'set -- "$1"/*;X=0;
for args; do [ -f "$args" ] && X=$((X+1)) ;done; [ "$X" -gt 1 ] ' _ {} \; -print
Pohon direktori.
.
├── 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
Hasil:
./test
./test/dir1
./test/dir2/dirb
test
dan dir2
direktori dalam pengujian saya (lihat jawaban saya).
test/x1
dan test/x2
sebagai file juga ... $1
dan $2
akan menjadi direktori untuk test
, dan direktori akan dilewatkan.
Lain find
+ wc
pendekatan:
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
- path ke direktori Anda saat ini
-maxdepth 1
- pertimbangkan hanya subfolder anak langsung
! -empty
- abaikan subfolder kosong
! -path "path/currdir"
- abaikan jalur direktori saat ini
count=$(find "$1" -maxdepth 1 -type f | wc -l)
- count
ditugaskan dengan jumlah file untuk setiap subfolder yang ditemukan
[ $count -ge 2 ] ... -print
- cetak nama / jalur subfolder yang berisi 2 atau lebih file biasa
find
. Dalam hal ini, karena GNUfind
akan memotong-motong nama direktori yang memiliki karakter yang tidak dapat dicetak di lokal saat ini (seperti "ä" di C locale). Lihat juga unix.stackexchange.com/questions/321697/…