कैसे `du` केवल उन फ़ाइलों द्वारा उपयोग की जाने वाली जगह है जो कहीं और हार्डलिंक नहीं की जाती हैं?


14

rsync --link-destअंतरिक्ष-बचत स्नैपशॉट के लिए उपयोग करते हुए , मैं यह कैसे पता लगा सकता हूं कि मैंने वास्तव में कितना स्थान बचाया है? या अधिक सामान्य:

यह पता लगाने के लिए कि एक डायरेक्टरी केवल उन्हीं फाइलों का उपयोग करने के लिए कितनी जगह का उपयोग करती है जो कि डायरेक्ट्री स्ट्रक्चर के बाहर कहीं और हार्डलिंक नहीं हैं ? अलग तरीके से पूछा गया: उस निर्देशिका को हटाने के बाद वास्तव में कितना स्थान खाली हो जाएगा? ( du -hsझूठ होगा। हार्डलिंक के लिए आवश्यक स्थान स्वयं शामिल हो सकता है)


2
डिफ़ॉल्ट रूप से, GNU duकेवल फ़ाइल आकारों को एक बार गिनता है, भले ही वे हार्ड लिंक से जुड़े हों जब तक कि आप -l/ --count-linksविकल्प का उपयोग न करें । आप duपूरे पेड़ पर दो बार दौड़ते हैं , उस विकल्प के साथ और उसके बिना और आकारों के बीच का अंतर होना चाहिए कि आपने सभी निर्देशिकाओं में कितना स्थान बचाया है।
jw013

1
यह भी देखें stackoverflow.com/questions/19951883/...
Rmano

जवाबों:


9

यह मानते हुए कि आंतरिक हार्डलिंक नहीं हैं (अर्थात, 1 से अधिक हार्डलिंक वाली प्रत्येक फ़ाइल को पेड़ के बाहर से जोड़ा गया है), आप यह कर सकते हैं:

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

संपादित करें और यहाँ मैंने टिप्पणी में क्या लिखा है, लागू किया गया। केवल बिना du; नोट करने के लिए यश @StephaneChazelas के लिए duआवश्यक नहीं है। अंत में स्पष्टीकरण।

( 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

हम जो कुछ भी करते हैं वह प्रत्येक प्रासंगिक फ़ाइल के डिस्क उपयोग (KB में) के साथ एक स्ट्रिंग बनाना है, जो प्लस साइन्स द्वारा अलग किया गया है। फिर हम उस बड़े को खिलाते हैं bc

पहला findमंगलाचरण निर्देशिकाओं के लिए करता है।

दूसरी findप्रिंट लिंक गिनती, इनोड और डिस्क उपयोग। हम उस सूची को पास sort | uniq -cकरने के लिए (पेड़ में दिखावे की संख्या, लिंक गणना, इनोड, डिस्क उपयोग) प्राप्त करते हैं।

हम उस सूची को पास करते हैंawk , और, यदि पहला फ़ील्ड (# दिखावे का) दूसरे (# हार्डलिंक) के बराबर या उससे अधिक है, जिसका अर्थ है कि पेड़ के बाहर से इस फ़ाइल के लिंक नहीं हैं, तो चौथे फ़ील्ड को प्रिंट करें ( डिस्क उपयोग) एक प्लस चिन्ह और एक बैकस्लैश संलग्न है।

अंत में हम एक आउटपुट करते हैं 0, इसलिए सूत्र वाक्य रचना में सही है (यह +अन्यथा में होगा ) और इसे पास करना होगा bc। ओह।

(लेकिन मैं सरल पहली विधि का उपयोग करूंगा, अगर यह एक अच्छा पर्याप्त उत्तर देता है।)


धन्यवाद, हाँ अगर वह आवश्यकता पूरी हो जाती है तो यह काम करता है। लेकिन अगर यह नहीं है?
तोबियस किंजलर

यह काम नहीं करता है क्योंकि यह स्वयं निर्देशिकाओं के आकार (जो आमतौर पर कम से कम 2 लिंक हैं, और यदि उनके पास नहीं था, तो आपके पास दो बार गिनी गई फाइलें होंगी) खाते के लिए विफल रहता है।
स्टीफन चेज़लस

1
फिर findसभी फ़ाइलों की सूची को उनके इनोड और लिंक काउंट के साथ प्रिंट करने के लिए उपयोग करना आवश्यक होगा ; फिर कुछ संयोजन sort | uniq -cप्राप्त करने के लिए पेड़ में प्रत्येक इनोड कितनी बार दिखाई देता है, फिर उन लिंक को फ़िल्टर करें जो दिखावे की संख्या से अधिक हैं ... और फिर उस सूची को फ़ीड करें du। लेकिन अगर आवश्यकता पूरी हो जाती है, तो प्रयास को बेहतर तरीके से बचाएं।
angus

@StephaneChazelas यह काम करता है, लेकिन यह सच है कि यह निर्देशिकाओं के अपने आकार के लिए जिम्मेदार नहीं है। अगर केवल duएक था -dपैरामीटर के समान lss '...
एंगस

यह भी ध्यान दें कि btrfsफाइलसिस्टम पर , निर्देशिकाओं के लिए लिंक की संख्या हमेशा होती है 1, इसलिए आपको ! -type d
स्टीफन चेज़लस

5

मूल रूप से, आपको सभी फ़ाइलों (गैर-निर्देशिका) के लिए इनोड संख्या और लिंक की संख्या प्राप्त करने की आवश्यकता है, प्रत्येक इनोड की घटना की संख्या के साथ लिंक की संख्या की तुलना करें, और यदि वे भिन्न होते हैं, तो फ़ाइल को बाहर करें।

यह मानते हुए, वे सभी एक ही फाइल सिस्टम पर हैं, कुछ इस तरह से काम करना चाहिए (GNU खोज के साथ):

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
     }'

हाँ, जो मैंने कहा (क्रेडिट के लिए धन्यवाद)। लेकिन निर्देशिकाओं की गिनती के द्वारा आपको जो अतिरिक्त सटीकता मिलती है, आप बिना डिस्क डिस्क का उपयोग करके खो देते हैं।
एंगस

@angus, "अथाह डिस्क उपयोग" से आपका क्या तात्पर्य है?
स्टीफन चेजलस

कुछ भी नहीं, मैं पूरी तरह से गलत था कि क्या %kरिपोर्ट की गई। यह बहुत अच्छा है, duइसकी बिल्कुल जरूरत नहीं है! घर पहुंचने पर मैं अपना जवाब अपडेट करूंगा। धन्यवाद!
कोण

3

du वास्तव में झूठ नहीं होगा;) यह dir (s) को पार्स करता है, जो इसे देता है, केवल सभी हार्डलिंक की पहली गणना करता है जो एक ही इनोड का संकेत देता है।

यदि आप पूछते हैं duकि यह केवल एक निर्देशिका में क्या देखता है, तो यह परवाह नहीं करता है कि एक ही सामग्री की ओर इशारा करते हुए अन्य कठिन लिंक हैं:

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

अब इसे एक ही पंक्ति पर दें (rsync वृद्धिशील बैकअप के लिए सबसे हाल ही में एक के साथ शुरू --link-dest)

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

या संपूर्ण बैकअप dir:

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

A daily.1 ’में कोई भी फाइल जो पहले से ही .0 daily.0’ में संदर्भित है, एक इनकोड (उर्फ "वास्तविक" फाइल) को संदर्भित नहीं करेगा।

इसलिए daily.1 को डिलीट करने से आपके डिवाइस पर 364MB की बचत होगी।

हटाना

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.