Làm thế nào để `du` chỉ có không gian được sử dụng bởi các tệp không được liên kết cứng ở nơi khác?


14

Sử dụng rsync --link-destcho ảnh chụp nhanh tiết kiệm không gian , làm thế nào tôi có thể tìm ra tôi thực sự tiết kiệm được bao nhiêu dung lượng? Hay nói chung hơn:

Làm thế nào để tìm ra bao nhiêu không gian thư mục sử dụng chỉ xem xét các tệp không được liên kết cứng ở nơi khác bên ngoài cấu trúc thư mục? Hỏi khác nhau: Bao nhiêu không gian thực sự sẽ được giải phóng sau khi xóa thư mục đó? ( du -hssẽ nói dối. Có thể bao gồm không gian cần thiết cho các liên kết cứng)


2
Theo mặc định, GNU duchỉ đếm kích thước tệp một lần ngay cả khi chúng được liên kết cứng trừ khi bạn sử dụng tùy chọn -l/ --count-links. Bạn chạy dutrên toàn bộ cây hai lần, có và không có tùy chọn đó và sự khác biệt giữa các kích thước sẽ là dung lượng bạn đã lưu trên tất cả các thư mục.
jw013

Câu trả lời:


9

Giả sử không có liên kết cứng nội bộ (nghĩa là mọi tệp có nhiều hơn 1 liên kết cứng được liên kết từ bên ngoài cây), bạn có thể làm:

find . -links -2 -print0 | du -c --files0-from=-

EDIT Và đây là những gì tôi phác thảo trong bình luận, áp dụng. Chỉ không có du; kudos đến @StephaneChazelas để nhận thấy dulà không cần thiết. Giải thích ở cuối.

( find . -type d -printf '%k + ' ; \
  find . \! -type d -printf '%n\t%i\t%k\n' | \
    sort | uniq -c                         | \
    awk '$1 >= $2 { print $4 " +\\" }' ; \
  echo 0 ) | bc

Những gì chúng tôi làm là tạo một chuỗi với việc sử dụng đĩa (tính bằng KB) của mỗi tệp có liên quan, được phân tách bằng dấu cộng. Sau đó, chúng tôi cho ăn bổ sung lớn đó bc.

Các findyêu cầu đầu tiên làm điều đó cho các thư mục.

Việc findin thứ hai liên kết đếm, inode và sử dụng đĩa. Chúng tôi chuyển danh sách đó qua sort | uniq -cđể có được danh sách (số lần xuất hiện trong cây, số lượng liên kết, inode, mức sử dụng đĩa).

Chúng tôi chuyển danh sách đó qua awkvà, nếu trường đầu tiên (# xuất hiện) lớn hơn hoặc bằng thứ hai (# của liên kết cứng), có nghĩa là không có liên kết đến tệp này từ bên ngoài cây, sau đó in trường thứ tư ( sử dụng đĩa) với dấu cộng và dấu gạch chéo ngược kèm theo.

Cuối cùng, chúng tôi xuất ra một 0công thức, vì vậy công thức là đúng về mặt cú pháp (nó sẽ +khác) và chuyển nó sang bc. Phù.

(Nhưng tôi sẽ sử dụng phương pháp đầu tiên đơn giản hơn, nếu nó cho câu trả lời đủ tốt.)


Cảm ơn, có nếu yêu cầu đó được thực hiện nó hoạt động. Nhưng nếu không phải thì sao?
Tobias Kienzler

Điều đó không hoạt động vì điều đó không tính đến kích thước của các thư mục (thường có ít nhất 2 liên kết và nếu không có, bạn sẽ có các tệp được tính hai lần).
Stéphane Chazelas

1
Sau đó, cần phải sử dụng findđể in danh sách tất cả các tệp có số lượng liên kết và số lượng liên kết của chúng; sau đó một số kết hợp sort | uniq -cđể có được bao nhiêu lần mỗi nút xuất hiện trong cây, sau đó lọc ra những cái có số lượng liên kết lớn hơn số lần xuất hiện ... và sau đó đưa danh sách đó vào du. Nhưng nếu yêu cầu được đáp ứng, tốt hơn hãy tiết kiệm công sức.
angus

@StephaneChazelas Nó hoạt động, nhưng sự thật là nó không chiếm kích thước riêng của các thư mục. Nếu chỉ ducó một -dtham số tương tự như ls...
angus

Cũng lưu ý rằng trên các btrfshệ thống tệp, số lượng liên kết cho các thư mục luôn luôn 1, vì vậy bạn cần thêm một! -type d
Stéphane Chazelas

5

Về cơ bản, bạn cần lấy số inode và số lượng liên kết cho tất cả các tệp (không phải thư mục), so sánh số lượng liên kết đó với số lần xuất hiện của mỗi inode và nếu chúng khác nhau, hãy loại trừ tệp.

Giả sử, tất cả chúng đều nằm trên cùng một hệ thống tệp, một cái gì đó như thế này sẽ hoạt động (với GNU find):

find . -type d -printf '%k\n' -o -printf '%i %n %k\n' |
   awk '
     NF==1{t+=$0; next}
     {n1[$1]=$2; n2[$1]++; s[$1]=$3}
     END {
       for (i in n1)
         if (n1[i] == n2[i])
           t+=s[i]
       print t
     }'

Vâng, những gì tôi đã nói (cảm ơn vì tín dụng). Nhưng độ chính xác cao hơn bạn có được bằng cách đếm các thư mục, bạn mất bằng cách thêm việc sử dụng đĩa không chính xác.
angus

@angus, ý của bạn là "sử dụng đĩa không chính xác" là gì?
Stéphane Chazelas

Không có gì, tôi đã hoàn toàn nhầm lẫn về những gì %kbáo cáo. Điều đó thật tuyệt, dukhông cần thiết chút nào! Tôi sẽ cập nhật câu trả lời của tôi khi tôi về nhà. Cảm ơn!
angus

3

du thực tế sẽ không nói dối;) Nó phân tích cú pháp (các) thư mục mà nó đưa ra, chỉ tính lần đầu tiên trong tất cả các liên kết cứng trỏ đến cùng một nút mà nó gặp.

Nếu bạn hỏi dunhững gì nó nhìn thấy chỉ trong một thư mục, thì không quan tâm rằng có các liên kết cứng khác trỏ đến cùng một nội dung:

$ du -h daily.0 && du -hc daily.1
29G /daily.0
29G /daily.1

Bây giờ hãy cung cấp cho nó các thư mục trên cùng một hàng (bắt đầu bằng một bản gần đây nhất cho các bản sao lưu gia tăng rsync với --link-dest):

$ du -hc daily.0 daily.1
29G /daily.0
364M /daily.1
29G total

Hoặc toàn bộ thư mục sao lưu:

$ du -hc --max-depth=1 /snapshots
29G /daily.0
364M /daily.1
537M /daily.2
333M /daily.3
30G total

Bất kỳ tệp nào trong 'Daily.1' tham chiếu đến một nút (hay còn gọi là tệp "thực") đã được tham chiếu trong 'Daily.0' sẽ không được tính.

Do đó, việc xóa hàng ngày.1 sẽ tiết kiệm 364MB trên thiết bị của bạn.

TẨY

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.