Làm thế nào để có được kích thước thư mục thực tế (ra khỏi du)?


17

Làm cách nào để có được kích thước thư mục thực tế, sử dụng các công cụ tiêu chuẩn UNIX / Linux?

Câu hỏi thay thế: Làm thế nào để tôi có được du cho tôi kích thước thư mục thực tế (không đĩa sử dụng)?

Vì mọi người dường như có các định nghĩa khác nhau về thuật ngữ "kích thước": Định nghĩa của tôi về "kích thước thư mục" là tổng của tất cả các tệp thông thường trong thư mục đó.

Tôi KHÔNG quan tâm đến kích thước của thư mục inode hoặc bất cứ điều gì (khối * kích thước khối) các tệp chiếm trên hệ thống tệp tương ứng. Một thư mục có 3 tệp, mỗi tệp 1 byte, có kích thước thư mục là 3 byte (theo định nghĩa của tôi).

Tính kích thước thư mục bằng cách sử dụng du dường như không đáng tin cậy.
Ví dụ: mkdir foo && du -b foobáo cáo "4096 foo", 4096 byte thay vì 0 byte. Với các thư mục rất lớn, kích thước thư mục được báo cáo du -hscó thể giảm 100 GB (!) Và hơn thế nữa (hệ thống tệp nén).

Vì vậy, những gì (công cụ / tùy chọn) phải được sử dụng để có được kích thước thư mục thực tế?


Hệ thống tập tin nào được sử dụng ở vị trí mới - đó có phải là xfscơ hội không?
Serge Vlasov


Và nếu FS mới của bạn thực sự là XFS, việc sử dụng đĩa tăng lên rất nhiều có lẽ là do sự phân bổ mạnh mẽ , làm giảm sự phân mảnh tệp với chi phí sử dụng đĩa.
Serge Vlasov

Câu trả lời:


8

Đây là tập lệnh hiển thị kích thước thư mục có thể đọc được của con người bằng các công cụ tiêu chuẩn Unix (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()}'

ví dụ:

$ ds ~        
72.891 GiB

Và bây giờ tôi tìm thấy một tùy chọn khác bị thiếu trong tất cả các lsyêu cầu được đề xuất ở đây : -q. Không có tùy chọn này, tập lệnh sẽ bị hỏng nếu một số tên tệp chứa các ký tự dòng mới. Viết kịch bản shell thực sự đáng tin cậy là quá khó khăn
Serge Vlasov

@SergeyVlasov Kịch bản tôi đã đăng không nên ngắt với các tệp như vậy, chỉ đơn thuần là bỏ qua các dòng bổ sung. Trường hợp vấn đề duy nhất sẽ xảy ra nếu một tệp được tạo cẩn thận có thêm một dòng với dấu hai chấm thứ năm có chứa một giá trị số. Đề nghị của bạn thực sự sẽ tránh được tình huống đó. Cảm ơn các mẹo, kịch bản cập nhật.
jlliagre

Câu trả lời đầy đủ. +1 cho bạn
ehime

Đây là một trong những giải pháp đáng tin cậy nhất. Nó hoạt động với tên tệp có dấu cách hoặc dấu ngoặc kép trong đó và nó in kích thước có thể đọc được.
cơ bản

@KIAaze Cảm ơn bạn đã xem xét và sửa mã của tôi!
jlliagre

8

Một số phiên bản duhỗ trợ đối số --apparent-sizeđể hiển thị kích thước rõ ràng thay vì sử dụng đĩa. Vì vậy, lệnh của bạn sẽ là:

du -hs --apparent-size

Từ các trang dành cho du kèm theo 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

1
không hoạt động: báo cáo một số không gian cho các thư mục trống
Karl Forner

1
Điều này làm việc cho tôi.
trỏ

2
Nó mang lại kích thước khác nhau đáng kể khi bạn so sánh các thư mục trên các hệ thống tệp khác nhau. Ví dụ, cùng một thư mục có kích thước rõ ràng là 290Gb trên hệ thống tệp zfs và 324Gb của exFat. Các giải pháp trên cho cùng kích thước.
Pixus.ru

4

Chỉ là một thay thế, sử dụng ls:

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

ls -nR: -nthích -l, nhưng liệt kê UID số và GID và -Rliệt kê các thư mục con theo cách đệ quy.

grep -v:Đảo ngược ý nghĩa của khớp, để chọn các dòng không khớp. (-v được chỉ định bởi POSIX.).'^ d'sẽ loại trừ các thư mục.

Lệnh Ls: http://linux.about.com/od/commands/l/blcmdl1_ls.htm

Người đàn ông Grep: http://linux.die.net/man/1/grep

BIÊN TẬP :

Chỉnh sửa như đề xuất @ Sergey Vlasov.


Sử dụng -ntùy chọn lsthay vì -l(hiển thị số UID / GID thay vì tên) sẽ an toàn hơn, vì tên người dùng và nhóm có thể chứa khoảng trắng (ví dụ: nếu winbindhoặc sssdđược sử dụng để tham gia hệ thống vào miền Windows, bạn có thể nhận được tên nhóm như domain users) . Nó cũng sẽ nhanh hơn do không cần tra cứu tên người dùng và nhóm.
Serge Vlasov

Cảm ơn, đây là NHIỀU nhanh hơn tìm -sec ls!
gpothier

4

Giả sử bạn có dutừ GNU coreutils, lệnh này sẽ tính tổng kích thước rõ ràng của số lượng tệp thông thường tùy ý trong một thư mục mà không có bất kỳ giới hạn tùy ý nào về số lượng tệp:

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

Thêm -ltùy chọn vào dunếu có một số tệp liên kết cứng bên trong và bạn muốn đếm riêng từng liên kết cứng (theo mặc địnhdu đếm nhiều liên kết cứng một lần).

Sự khác biệt quan trọng nhất với đơn giản du -sblà đệ quy ducũng tính kích thước của các thư mục, được báo cáo khác nhau bởi các hệ thống tệp khác nhau; để tránh điều này, findlệnh được sử dụng để chỉ truyền các tệp thông thường tới du. Một sự khác biệt nữa là các liên kết tượng trưng bị bỏ qua (nếu chúng cần được tính, findlệnh sẽ được điều chỉnh).

Lệnh này cũng sẽ tiêu thụ bộ nhớ nhiều hơn đồng bằng du -sb, bởi vì sử dụng --files0-from=FILElàm ducửa hàng thiết bị và inode số của tất cả các tập tin xử lý, như trái ngược với hành vi mặc định chỉ nhớ các file với nhiều hơn một liên kết cứng. (Đây không phải là vấn đề nếu -ltùy chọn được sử dụng để đếm liên kết cứng nhiều lần, vì lý do duy nhất để lưu trữ số thiết bị và số inode là bỏ qua các tệp liên kết cứng đã được xử lý.)

Nếu bạn muốn có được một đại diện có thể đọc được của con người về tổng kích thước, chỉ cần thêm -htùy chọn (điều này hoạt động vì duchỉ được gọi một lần và tự tính tổng kích thước, không giống như một số câu trả lời được đề xuất khác):

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

hoặc (nếu bạn lo lắng rằng một số hiệu ứng -bsau đó bị ghi đè -h)

find . -type f -print0 | du -sc --apparent-size -h --files0-from=- | tail -n 1

Không chắc chắn phải làm gì cho FreeBSD - mặc dù -bcó thể được thay thế bằng -A -B 1, nhưng không có gì tương đương --files0-from=-và việc sử dụng xargssẽ cần một số cách giải quyết trong trường hợp danh sách tệp lớn hơn ARG_MAX(và một số giải pháp bên ngoài cho đầu ra có thể đọc được của con người).
Serge Vlasov

3

Nếu tất cả những gì bạn muốn là kích thước của các tệp, không bao gồm dung lượng thư mục chiếm, bạn có thể làm một cái gì đó như

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

@SergeyVlasov chỉ ra rằng điều này sẽ thất bại nếu bạn có nhiều tệp hơn argmax. Để tránh điều đó, bạn có thể sử dụng một cái gì đó như:

find . -type f -exec du -sb '{}' \; | gawk '{k+=$1}END{print k}'

1
Lệnh này sẽ âm thầm đưa ra một kết quả sai nếu thư mục chứa quá nhiều tệp mà chúng không phù hợp với giới hạn về kích thước đối số execve () trong trường hợp xargsnày sẽ gọi dunhiều lần và mỗi lệnh gọi sẽ in tổng cộng chỉ cho phần của nó của danh sách tập tin hoàn chỉnh, sau đó tailsẽ chỉ hiển thị tổng kích thước của phần cuối cùng.
Serge Vlasov

1
@SergeyVlasov điểm tốt, tôi đã không nghĩ về điều đó, cảm ơn, câu trả lời được cập nhật.
terdon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.