Bagaimana cara mendapatkan ukuran direktori aktual (out of du)?

17

Bagaimana cara mendapatkan ukuran direktori aktual, menggunakan alat standar UNIX / Linux?

Pertanyaan alternatif: Bagaimana saya meminta du untuk menunjukkan ukuran direktori yang sebenarnya (bukan penggunaan disk)?

Karena orang tampaknya memiliki definisi yang berbeda dari istilah "ukuran": Definisi saya tentang "ukuran direktori" adalah jumlah semua file biasa dalam direktori itu.

Saya TIDAK peduli tentang ukuran inode direktori atau apa pun (blok * ukuran blok) file mengambil pada sistem file masing-masing. Direktori dengan 3 file, masing-masing 1 byte, memiliki ukuran direktori 3 byte (menurut definisi saya).

Menghitung ukuran direktori menggunakan du tampaknya tidak dapat diandalkan.
Misalnya, mkdir foo && du -b foomelaporkan "4096 foo", 4096 byte, bukan 0 byte. Dengan direktori yang sangat besar, ukuran direktori dilaporkan olehdu -hs dapat dimatikan sebesar 100 GB (!) Dan lainnya (sistem file terkompresi).

Jadi apa (alat / opsi) harus digunakan untuk mendapatkan ukuran direktori yang sebenarnya?

basic6
sumber
Filesystem apa yang digunakan di lokasi baru - apakah xfskebetulan?
Sergey Vlasov
Dan jika FS baru Anda benar-benar XFS, penggunaan disk sangat meningkat mungkin karena preallokasi agresif , yang mengurangi fragmentasi file dengan biaya penggunaan disk.
Sergey Vlasov

Jawaban:

8

Berikut ini adalah skrip yang menampilkan ukuran direktori yang dapat dibaca manusia menggunakan Unix standard tools (POSIX).

#!/bin/sh
find ${1:-.} -type f -exec ls -lnq {} \+ | awk '
BEGIN {sum=0} # initialization for clarity and safety
function pp() {
  u="+Ki+Mi+Gi+Ti+Pi+Ei";
  split(u,unit,"+");
  v=sum;
  for(i=1;i<7;i++) {
    if(v<1024) break;
    v/=1024;
  }
  printf("%.3f %sB\n", v, unit[i]);
}
{sum+=$5}
END{pp()}'

misalnya:

$ ds ~        
72.891 GiB
Jlliagre
sumber
Dan sekarang saya menemukan pilihan lain yang hilang dalam semua disarankan lsdoa di sini: -q. Tanpa opsi ini skrip akan pecah jika beberapa nama file berisi karakter baris baru. Menulis skrip shell yang benar-benar andal terlalu sulit ...
Sergey Vlasov
@SergeyVlasov Script yang saya posting tidak boleh pecah dengan file seperti itu, hanya mengabaikan baris tambahan. Satu-satunya kasus masalah akan terjadi jika file yang dibuat dengan hati-hati memiliki garis ekstra dengan usus besar kelima yang berisi nilai numerik. Saran Anda tentu akan menghindari situasi itu. Terima kasih atas tipnya, skrip diperbarui.
jlliagre
Jawaban yang sangat bagus. +1 untuk Anda pak
ehime
Ini adalah salah satu solusi paling andal. Ini bekerja dengan nama file yang memiliki spasi atau tanda kutip di dalamnya dan ia mencetak ukuran yang bisa dibaca manusia.
basic6
@KIAaze Terima kasih telah meninjau dan memperbaiki kode saya!
jlliagre
8

Beberapa versi dumendukung argumen --apparent-sizeuntuk menunjukkan ukuran yang tampak alih-alih penggunaan disk. Jadi perintah Anda adalah:

du -hs --apparent-size

Dari halaman manual untuk du disertakan dengan Ubuntu 12,04 LTS:

--apparent-size
      print apparent sizes,  rather  than  disk  usage;  although  the
      apparent  size is usually smaller, it may be larger due to holes
      in (`sparse') files, internal  fragmentation,  indirect  blocks,
      and the like
Brian
sumber
1
tidak berfungsi: laporkan beberapa ruang untuk direktori kosong
Karl Forner
1
ini berhasil untuk saya.
connorbode
2
Ini memberikan ukuran yang sangat berbeda ketika Anda membandingkan direktori pada sistem file yang berbeda. Misalnya folder yang sama memiliki ukuran 290Gb pada sistem file zfs dan 324Gb dari exFat. Solusi di atas memberikan ukuran yang sama.
Pixus.ru
4

Hanya sebuah alternatif, menggunakan ls:

ls -nR | grep -v '^d' | awk '{total += $5} END {print total, "Total"}'

ls -nR: -nseperti -l, tetapi daftar UID angka dan GID dan -Rdaftar subdirektori secara rekursif.

grep -v:Balikkan indra pencocokan, untuk memilih jalur yang tidak cocok. (-v ditentukan oleh POSIX.). '^ d'akan mengecualikan direktori.

Perintah Ls: http://linux.about.com/od/commands/l/blcmdl1_ls.htm

Man Grep: http://linux.die.net/man/1/grep

EDIT :

Diedit sebagai saran @ Sergey Vlasov.

stderr
sumber
Menggunakan -nopsi lsalih - alih -l(menampilkan nomor UID / GID alih-alih nama) lebih aman, karena nama pengguna dan grup dapat berisi spasi (misalnya, jika winbindatau sssddigunakan untuk bergabung dengan sistem ke domain Windows, Anda bisa mendapatkan nama grup seperti domain users) . Itu juga harus lebih cepat karena tidak perlu mencari nama pengguna dan grup.
Sergey Vlasov
Terima kasih, ini JAUH lebih cepat daripada menemukan -exec!
gpothier
4

Dengan asumsi Anda memiliki dudari GNU coreutils, perintah ini harus menghitung ukuran nyata total jumlah file acak di dalam direktori tanpa batasan arbitrer pada jumlah file:

find . -type f -print0 | du -scb --files0-from=- | tail -n 1

Tambahkan -lopsi ke dujika ada beberapa file hardlink di dalamnya, dan Anda ingin menghitung setiap hardlink secara terpisah (secara defaultdu menghitung beberapa hardlink hanya sekali).

Perbedaan paling penting dengan plain du -sbadalah bahwa rekursif dujuga menghitung ukuran direktori, yang dilaporkan secara berbeda oleh sistem file yang berbeda; untuk menghindari ini, findperintah yang digunakan hanya meneruskan file biasa du. Perbedaan lain adalah bahwa symlink diabaikan (jika harus dihitung, thefind perintahnya harus disesuaikan).

Perintah ini juga akan mengkonsumsi lebih banyak memori daripada sekadar plain du -sb, karena menggunakan --files0-from=FILEmake dustore device dan nomor inode dari semua file yang diproses, berbeda dengan perilaku default yaitu hanya mengingat file dengan lebih dari satu hard link. (Ini bukan masalah jika -lopsi digunakan untuk menghitung hardlink beberapa kali, karena satu-satunya alasan untuk menyimpan nomor perangkat dan inode adalah untuk melewati file-file hardlink yang sudah diproses.)

Jika Anda ingin mendapatkan representasi ukuran total yang dapat dibaca manusia, cukup tambahkan -hopsi (ini berfungsi karena dudipanggil hanya sekali dan menghitung ukuran total itu sendiri, tidak seperti beberapa jawaban yang disarankan lainnya):

find . -type f -print0 | du -scbh --files0-from=- | tail -n 1

atau (jika Anda khawatir bahwa beberapa efek -bkemudian ditimpa oleh -h)

find . -type f -print0 | du -sc --apparent-size -h --files0-from=- | tail -n 1
Sergey Vlasov
sumber
Tidak yakin apa yang harus dilakukan untuk FreeBSD - walaupun -bmungkin dapat digantikan oleh -A -B 1, tidak ada yang setara dengan --files0-from=-, dan menggunakan xargsakan memerlukan beberapa solusi jika daftar file lebih besar dari ARG_MAX(dan beberapa solusi eksternal untuk output yang dapat dibaca manusia).
Sergey Vlasov
3

Jika yang Anda inginkan adalah ukuran file, tidak termasuk ruang yang digunakan direktori, Anda dapat melakukan sesuatu seperti

find . -type f -print0 | xargs -0 du -scb | tail -n 1

@SergeyVlasov menunjukkan bahwa ini akan gagal jika Anda memiliki lebih banyak file daripada argmax. Untuk menghindari itu Anda bisa menggunakan sesuatu seperti:

find . -type f -exec du -sb '{}' \; | gawk '{k+=$1}END{print k}'
terdon
sumber
1
Perintah ini akan secara diam-diam memberikan hasil yang salah jika direktori berisi begitu banyak file yang tidak sesuai dengan batas pada execve () ukuran argumen - dalam hal ini xargsakan dipanggil dubeberapa kali, dan setiap doa akan mencetak total total hanya untuk bagiannya dari daftar file lengkap, maka tailhanya akan menunjukkan ukuran total dari bagian terakhir.
Sergey Vlasov
1
@SergeyVlasov poin bagus, saya tidak memikirkan itu, terima kasih, jawabannya diperbarui.
terdon