Saya mencoba mencari cara terbaik untuk menemukan jumlah file di direktori tertentu ketika ada jumlah file yang sangat besar (> 100.000).
Ketika ada banyak file, melakukan ls | wc -l
membutuhkan waktu yang cukup lama untuk dieksekusi. Saya percaya ini karena mengembalikan nama semua file. Saya mencoba mengambil IO disk sesedikit mungkin.
Saya telah bereksperimen dengan beberapa shell dan skrip Perl tidak berhasil. Ada ide?
Jawaban:
Secara default
ls
mengurutkan nama, yang bisa memakan waktu cukup lama jika ada banyak dari mereka. Juga tidak akan ada output sampai semua nama dibaca dan disortir. Gunakanls -f
opsi untuk mematikan penyortiran.Catatan bahwa ini juga akan memungkinkan
-a
, jadi.
,..
file, dan lain dimulai dengan.
akan dihitung.sumber
ls
.stat()
panggilan yangls
dilakukan pada setiap file.find
tidakstat()
dengan demikian bekerja lebih cepat.ls -f
juga tidakstat()
. Tapi tentu saja keduanyals
danfind
meneleponstat()
ketika opsi tertentu digunakan, sepertils -l
ataufind -mtime
.ls -fR | wc -l
Cara tercepat adalah program yang dibuat khusus, seperti ini:
Dari pengujian saya tanpa memperhatikan cache, saya menjalankan masing-masing sekitar 50 kali masing-masing terhadap direktori yang sama, berulang-ulang, untuk menghindari kemiringan data berbasis cache, dan saya mendapat kira-kira angka kinerja berikut (dalam waktu jam nyata):
Yang terakhir
dircnt
,, adalah program yang disusun dari sumber di atas.EDIT 2016-09-26
Karena banyaknya permintaan, saya menulis ulang program ini agar bersifat rekursif, sehingga akan masuk ke subdirektori dan terus menghitung file dan direktori secara terpisah.
Karena jelas beberapa orang ingin tahu bagaimana melakukan semua ini, saya punya banyak komentar dalam kode untuk mencoba memperjelas apa yang terjadi. Saya menulis ini dan mengujinya di Linux 64-bit, tetapi seharusnya bekerja pada sistem yang mendukung POSIX, termasuk Microsoft Windows. Laporan bug diterima; Saya senang memperbarui ini jika Anda tidak bisa membuatnya bekerja pada AIX atau OS / 400 Anda atau apa pun.
Seperti yang Anda lihat, ini jauh lebih rumit daripada yang asli dan tentu saja demikian: setidaknya satu fungsi harus ada untuk dipanggil secara rekursif kecuali jika Anda ingin kode menjadi sangat kompleks (misalnya mengelola tumpukan subdirektori dan memprosesnya dalam satu loop). Karena kita harus memeriksa jenis file, perbedaan antara OS yang berbeda, perpustakaan standar, dll ikut bermain, jadi saya telah menulis sebuah program yang mencoba untuk dapat digunakan pada sistem mana pun yang akan dikompilasi.
Ada sangat sedikit pengecekan kesalahan, dan
count
fungsinya sendiri tidak benar-benar melaporkan kesalahan. Satu-satunya panggilan yang benar-benar dapat gagal adalahopendir
danstat
(jika Anda tidak beruntung dan memiliki sistem di mana sudahdirent
berisi jenis file). Saya tidak paranoid tentang memeriksa panjang total nama path subdir, tetapi secara teoritis, sistem seharusnya tidak mengizinkan nama path yang lebih panjang dari padaPATH_MAX
. Jika ada masalah, saya dapat memperbaikinya, tetapi hanya kode yang perlu dijelaskan kepada seseorang yang sedang belajar menulis C. Program ini dimaksudkan untuk menjadi contoh tentang bagaimana menyelami subdirektori secara rekursif.EDIT 2017-01-17
Saya telah memasukkan dua perubahan yang disarankan oleh @FlyingCodeMonkey:
lstat
sebagai gantistat
. Ini akan mengubah perilaku program jika Anda memiliki direktori yang disinkronkan di direktori yang Anda pindai. Perilaku sebelumnya adalah bahwa subdirektori (ditautkan) akan memiliki jumlah file ditambahkan ke jumlah keseluruhan; perilaku baru adalah bahwa direktori yang ditautkan akan dihitung sebagai satu file, dan isinya tidak akan dihitung.EDIT 2017-06-29
Dengan sedikit keberuntungan, ini akan menjadi edit terakhir dari jawaban ini :)
Saya telah menyalin kode ini ke dalam repositori GitHub untuk membuatnya sedikit lebih mudah untuk mendapatkan kode (alih-alih menyalin / menempel, Anda dapat mengunduh sumbernya ), ditambah lagi membuatnya lebih mudah bagi siapa saja untuk menyarankan modifikasi dengan mengirimkan tarikan -meminta bantuan dari GitHub.
Sumber tersedia di bawah Apache License 2.0. Tambalan * selamat datang!
sumber
gcc -o dircnt dircnt.c
dan gunakan seperti ini./dircnt some_dir
Apakah Anda mencoba mencari? Sebagai contoh:
sumber
find /usr/share | wc -l
(~ 137.000 file) sekitar 25% lebih cepat daripadals -R /usr/share | wc -l
(~ 160.000 baris termasuk nama dir, total dir dan baris kosong) pada jalankan pertama masing-masing dan setidaknya dua kali lebih cepat ketika membandingkan berjalan (cache) berikutnya.find
lebih cepat daripadals
karena cara Anda menggunakanls
. Jika Anda berhenti menyortir,ls
danfind
memiliki kinerja serupa.temukan, ls dan perl diuji terhadap 40.000 file: kecepatan yang sama (meskipun saya tidak mencoba menghapus cache):
dan dengan perl opendir / readdir, waktu yang sama:
Catatan: Saya menggunakan / bin / ls -f untuk memastikan mem-bypass opsi alias yang mungkin sedikit melambat dan -f untuk menghindari pemesanan file. ls tanpa -f dua kali lebih lambat dari find / perl kecuali jika ls digunakan dengan -f, tampaknya waktu yang sama:
Saya juga ingin memiliki beberapa skrip untuk menanyakan sistem file secara langsung tanpa semua informasi yang tidak perlu.
tes berdasarkan jawaban Peter van der Heijden, glenn jackman dan mark4o.
Thomas
sumber
ls -l | wc -l
folder pada HDD 2.5 "eksternal dengan file 1M, dibutuhkan sekitar 3 menit untuk operasi untuk menyelesaikan. Kedua kalinya dibutuhkan 12 detik IIRC. Juga ini berpotensi berpotensi bergantung pada sistem file Anda juga. Saya menggunakanBtrfs
.$ time perl -e 'opendir D, "."; @files = readdir D; closedir D; print scalar(@files)."\n"' 1315029 real 0m0.580s user 0m0.302s sys 0m0.275s
Anda dapat mengubah output berdasarkan kebutuhan Anda, tetapi di sini ada bash one-liner yang saya tulis untuk menghitung secara rekursif dan melaporkan jumlah file dalam serangkaian direktori bernama numerik.
Ini terlihat secara rekursif untuk semua file (bukan direktori) di direktori yang diberikan dan mengembalikan hasilnya dalam format seperti hash. Perubahan sederhana pada perintah find dapat membuat jenis file apa yang Anda cari lebih spesifik, dll.
Menghasilkan sesuatu seperti ini:
sumber
ls -1 ${dir}
tidak akan berfungsi dengan baik tanpa lebih banyak ruang. Juga, tidak ada jaminan bahwa nama yang dikembalikan olehls
dapat diteruskan kefind
, karenals
lolos dari karakter yang tidak dapat dicetak untuk konsumsi manusia. (mkdir $'oddly\nnamed\ndirectory'
jika Anda ingin test case yang sangat menarik). Lihat Mengapa Anda tidak perlu menguraikan output ls (1)Anehnya bagi saya, menemukan tulang kosong sangat sebanding dengan ls-f
melawan
Tentu saja, nilai-nilai pada desimal ketiga bergeser sedikit setiap kali Anda mengeksekusi semua ini, jadi mereka pada dasarnya identik. Namun perhatikan bahwa
find
mengembalikan satu unit tambahan, karena ia menghitung direktori aktual itu sendiri (dan, seperti yang disebutkan sebelumnya,ls -f
mengembalikan dua unit tambahan, karena ia juga menghitung. Dan ..).sumber
Hanya menambahkan ini demi kelengkapan. Jawaban yang benar tentu saja sudah diposting oleh orang lain, tetapi Anda juga bisa mendapatkan hitungan file dan direktori dengan program tree.
Jalankan perintah
tree | tail -n 1
untuk mendapatkan baris terakhir, yang akan mengatakan sesuatu seperti "763 direktori, 9290 file". Ini menghitung file dan folder secara rekursif, tidak termasuk file tersembunyi, yang dapat ditambahkan dengan bendera-a
. Untuk referensi, butuh 4,8 detik di komputer saya, untuk pohon menghitung seluruh dir rumah saya, yang merupakan 24.777 direktori, 238680 file.find -type f | wc -l
butuh 5,3 detik, setengah detik lebih lama, jadi saya pikir pohon cukup kompetitif dari segi kecepatan.Selama Anda tidak memiliki subfolder, tree adalah cara cepat dan mudah untuk menghitung file.
Juga, dan murni untuk bersenang-senang, Anda dapat menggunakan
tree | grep '^├'
hanya menampilkan file / folder di direktori saat ini - ini pada dasarnya adalah versi yang jauh lebih lambatls
.sumber
Brew install tail
untuk OS X.tail
seharusnya sudah diinstal pada sistem Mac OS X Anda.Hitungan File Linux Cepat
Hitungan file linux tercepat yang saya tahu adalah
Tidak ada kebutuhan untuk memohon grep! Tetapi seperti yang disebutkan Anda harus memiliki database baru (diperbarui setiap hari oleh pekerjaan cron, atau manual oleh
sudo updatedb
).Dari man loc
Tambahan Anda harus tahu bahwa itu juga menghitung direktori sebagai file!
BTW: Jika Anda ingin ikhtisar file dan direktori pada jenis sistem Anda
Ini menghasilkan jumlah direktori, file dll.
sumber
Menulis ini di sini karena saya tidak memiliki poin reputasi yang cukup untuk mengomentari jawaban, tetapi saya diizinkan untuk meninggalkan jawaban saya sendiri jawaban , yang tidak masuk akal. Bagaimanapun...
Mengenai jawaban oleh Christopher Schultz , saya sarankan mengubah stat ke lstat dan mungkin menambahkan batas-cek untuk menghindari buffer overflow:
Saran untuk menggunakan lstat adalah untuk menghindari symlink berikut yang dapat menyebabkan siklus jika direktori berisi symlink ke direktori induk.
sumber
lstat
adalah saran yang bagus dan Anda pantas mendapatkan karma untuk itu. Saran ini dimasukkan ke dalam kode saya yang diposting di atas dan, sekarang, di GitHub.Anda bisa mencoba jika menggunakan
opendir()
danreaddir()
diPerl
lebih cepat. Untuk contoh fungsi tersebut lihat di sinisumber
Jawaban di sini lebih cepat daripada hampir semua hal lain di halaman ini untuk direktori yang sangat besar, sangat bersarang:
https://serverfault.com/a/691372/84703
locate -r '.' | grep -c "^$PWD"
sumber
locate -c -r '/path'
seperti dalam solusiSaya datang ke sini ketika mencoba menghitung file dalam dataset ~ 10K folder dengan ~ 10K masing-masing file. Masalah dengan banyak pendekatan adalah bahwa mereka secara implisit stat file 100M, yang membutuhkan waktu lama.
Saya mengambil kebebasan untuk memperluas pendekatan oleh christopher-schultz sehingga mendukung lewat direktori melalui args (pendekatan rekursifnya menggunakan stat juga).
Masukkan yang berikut ke dalam file
dircnt_args.c
:Setelah
gcc -o dircnt_args dircnt_args.c
Anda dapat memanggilnya seperti ini:Pada 100M file dalam folder 10K di atas selesai dengan cukup cepat (~ 5 mnt untuk menjalankan pertama, tindak lanjuti cache: ~ 23 dtk).
Satu-satunya pendekatan lain yang selesai dalam waktu kurang dari satu jam itu ls dengan sekitar 1 menit pada cache:
ls -f /your/dirs/* | wc -l
. Hitungan dimatikan oleh beberapa baris baru per dir meskipun ...Selain yang diharapkan, tidak ada upaya saya dengan
find
kembali dalam waktu satu jam: - /sumber
Cara tercepat di linux (pertanyaannya ditandai sebagai linux), adalah menggunakan panggilan sistem langsung. Berikut adalah program kecil yang menghitung file (hanya, tanpa dir) di direktori. Anda dapat menghitung jutaan file dan ini sekitar 2,5 kali lebih cepat dari "ls -f" dan sekitar 1,3-1,5 kali lebih cepat dari jawaban Christopher Schultz.
PS: Itu tidak rekursif tetapi Anda bisa memodifikasinya untuk mencapainya.
sumber
opendir
/readdir
, tapi saya menduga itu bermuara pada kode yang hampir sama pada akhirnya. Membuat panggilan sistem dengan cara itu juga tidak portabel dan, karena Linux ABI tidak stabil, program yang dikompilasi pada satu sistem tidak dijamin berfungsi dengan baik pada sistem lain (walaupun itu saran yang cukup baik untuk mengkompilasi apa pun dari sumber pada sistem * NIX IMO ). Jika kecepatan adalah kunci, ini adalah solusi yang baik jika itu benar-benar meningkatkan kecepatan - saya belum membandingkan program secara terpisah.ls
menghabiskan lebih banyak waktu menyortir nama file, menggunakan-f
untuk menonaktifkan penyortiran akan menghemat waktu:atau Anda dapat menggunakan
find
:sumber
Saya menyadari bahwa tidak menggunakan dalam pemrosesan memori ketika Anda memiliki sejumlah besar data lebih cepat daripada "memipakan" perintah. Jadi saya menyimpan hasilnya ke file dan setelah menganalisisnya
sumber
Anda harus menggunakan "getdents" sebagai ganti ls / find
Berikut ini adalah satu artikel yang sangat bagus yang menggambarkan pendekatan getdents.
http://be-n.com/spw/you-can-list-a-million-files-in-a-directory-but-not-with-ls.html
Ini ekstraknya:
ls dan praktis setiap metode lain untuk mendaftarkan direktori (termasuk python os.listdir, find.) bergantung pada libc readdir (). Namun readdir () hanya membaca 32K entri direktori pada suatu waktu, yang berarti bahwa jika Anda memiliki banyak file di direktori yang sama (mis. 500M entri direktori) akan memakan waktu sangat lama untuk membaca semua entri direktori , terutama pada disk yang lambat. Untuk direktori yang berisi banyak file, Anda harus menggali lebih dalam daripada alat yang mengandalkan readdir (). Anda perlu menggunakan getdents () syscall secara langsung, daripada metode pembantu dari libc.
Kita dapat menemukan kode C untuk mendaftar file menggunakan getdents () dari sini :
Ada dua modifikasi yang perlu Anda lakukan agar daftar semua file dalam direktori dengan cepat.
Pertama, tingkatkan ukuran buffer dari X menjadi sekitar 5 megabita.
Kemudian modifikasi loop utama di mana ia mencetak informasi tentang setiap file dalam direktori untuk melewati entri dengan inode == 0. Saya melakukan ini dengan menambahkan
Dalam kasus saya, saya juga benar-benar hanya peduli tentang nama file di direktori jadi saya juga menulis ulang pernyataan printf () untuk hanya mencetak nama file.
Kompilasi (tidak perlu perpustakaan eksternal, jadi sangat mudah dilakukan)
Sekarang jalankan
sumber
readdir()
sebenarnya tidak lambat. Saya perlu angka yang kuat sebelum saya percaya bahwa ada baiknya membuang portabilitas untuk mendapatkan kinerja ini.Saya lebih suka perintah berikut untuk melacak perubahan jumlah file dalam direktori.
Perintah akan membuat jendela terbuka untuk melacak jumlah file yang ada di direktori dengan kecepatan refresh 0,1 detik.
sumber
ls | wc -l
akan selesai untuk folder dengan ribuan atau jutaan file dalam 0,01? bahkan Andals
sangat tidak efisien dibandingkan dengan solusi lain. Dan OP hanya ingin mendapatkan hitungan, tidak duduk di sana melihat output berubahwatch
manual setelah komentar itu dan melihat bahwa 0,01s (bukan 0,1s) adalah angka yang tidak realistis karena kecepatan refresh sebagian besar layar PC hanya 60Hz, dan ini tidak menjawab pertanyaan dengan cara apa pun. OP bertanya tentang "Jumlah File Linux Cepat untuk sejumlah besar file". Anda juga tidak membaca jawaban yang tersedia sebelum memposting10 direktori pertama dengan no tertinggi file.
sumber