विरल फ़ाइलें ढूँढना?


19

क्या मेरे सिस्टम पर, या किसी विशेष निर्देशिका ट्री में सभी विरल फ़ाइलों को खोजने का एक सीधा तरीका है?

यदि यह प्रासंगिक है, तो मैं zshUbuntu 12.04 पर उपयोग कर रहा हूं , हालांकि बैश / श के लिए एक अधिक सामान्य यूनिक्स-वाई उत्तर, उदाहरण के लिए, ठीक होगा।

संपादित करें : स्पष्ट करने के लिए, मैं विरल फाइलों की खोज कर रहा हूं, किसी एक की स्पार्सनेस स्थिति की जांच नहीं कर रहा हूं।



2
क्या आपको लगता है कि विरल फ़ाइलों की खोज में व्यक्तिगत लोगों की दुर्लभता स्थिति की जाँच शामिल नहीं है?
jlliagre

जवाबों:


11

सिस्टम पर (और फ़ाइल सिस्टम) SEEK_HOLE lseekझंडे का समर्थन करना (जैसे आपके Ubuntu 12.04 ext4 पर) और मान SEEK_HOLEलेना 4 के लिए है क्योंकि यह लिनक्स पर है:

if perl -le 'seek STDIN,0,4;$p=tell STDIN;
   seek STDIN,0,2; exit 1 if $p == tell STDIN'< the-file; then
  echo the-file is sparse
else
  echo the-file is not sparse
fi

वह शेल सिंटैक्स POSIX है। इसमें गैर-पोर्टेबल सामान हैं perlऔर वह है SEEK_HOLE

lseek(SEEK_HOLE)फ़ाइल में पहला छेद शुरू करने का प्रयास करता है , या कोई छेद नहीं मिलने पर फ़ाइल का अंत। ऊपर हम जानते हैं कि फ़ाइल विरल नहीं है जब lseek(SEEK_HOLE)हमें फ़ाइल के अंत में ले जाता है (जैसे ही उसी स्थान पर lseek(SEEK_END))।

यदि आप विरल फ़ाइलों को सूचीबद्ध करना चाहते हैं:

find . -type f ! -size 0 -exec perl -le 'for(@ARGV){open(A,"<",$_)or
  next;seek A,0,4;$p=tell A;seek A,0,2;print if$p!=tell A;close A}' {} +

GNU find(संस्करण 4.3.3 के बाद से) को किसी फ़ाइल -printf %Sकी विरलता की रिपोर्ट करनी होती है। यह फ्रॉस्ट्सचुट्ज़ के उत्तर के समान दृष्टिकोण लेता है, जिसमें यह डिस्क उपयोग बनाम फ़ाइल आकार का अनुपात लेता है, इसलिए सभी विरल फ़ाइलों की रिपोर्ट करने की गारंटी नहीं है (जैसे कि जब फ़ाइल सिस्टम स्तर पर संपीड़न होता है या जहां छेद द्वारा बचाया गया स्थान नहीं होता है फाइलसिस्टम इंफ्रास्ट्रक्चर के लिए क्षतिपूर्ति ओवरहेड या बड़ी विस्तारित विशेषताओं), लेकिन उन प्रणालियों पर काम करेगा जिनके पास SEEK_HOLEया फाइल सिस्टम SEEK_HOLEनहीं है जहां लागू नहीं किया गया है। यहाँ GNU टूल्स के साथ:

find . -type f ! -size 0 -printf '%S:%p\0' |
  awk -v RS='\0' -F : '$1 < 1 {sub(/^[^:]*:/, ""); print}'

(ध्यान दें कि इस उत्तर के पहले संस्करण ने ठीक से काम नहीं किया था जब findउदाहरण 3.2e-05 के रूप में विरलता व्यक्त की थी। मेरे ध्यान में लाने के लिए @ फ्लैशिडेव के उत्तर के लिए धन्यवाद )


ऊपर के रूप में एक ही टिप्पणी; मैं सभी विरल फ़ाइलों को खोजने का एक तरीका खोज रहा हूँ, किसी विशेष फ़ाइल की जाँच नहीं कर रहा हूँ।
एंड्रयू फेरियर

1
शायद find0-बाइट-फ़ाइलों को भी एकमुश्त बाहर कर देना चाहिए?
फ्रॉस्ट्सचुट्ज़

@frostschutz, अच्छी बात है, उत्तर अपडेट किया गया।
स्टीफन चेजलस

साथ अच्छा लगा find -printf '%S'! :-)
फ्रॉस्ट्सचुट्ज़ १४'१३ को

1
@Brian, की जगह trकमांड के साथxargs -r0 rm -f
स्टीफन Chazelas

8

एक फ़ाइल आमतौर पर विरल होती है, जब आवंटित ब्लॉक की संख्या फ़ाइल के आकार से छोटी होती है (यहां GNU का उपयोग statउबंटू पर पाया गया है, लेकिन अन्य सिस्टम के असंगत कार्यान्वयन हो सकते हैं stat)।

if [ "$((`stat -c '%b*%B-%s' -- "$file"`))" -lt 0 ]
then
    echo "$file" is sparse
else
    echo "$file" is not sparse
fi

वेरिएंट के साथ find: (स्टीफन से चोरी)

find . -type f ! -size 0 -exec bash -c '
    for f do
        [ "$((`stat -c "%b*%B-%s" -- "$f"`))" -lt 0 ] && printf "%s\n" "$f";
    done' {} +

आप इसे आमतौर पर शेल स्क्रिप्ट में डाल सकते हैं, फिर शेल स्क्रिप्ट निष्पादित करें।

find . -type f ! -size 0 -exec ./sparsetest.sh {} +

यदि स्पार्स ब्लॉक पारंपरिक फ़ाइल सिस्टम में ओवरराइड ब्लॉक के ओवरहेड के लिए कवर करने के लिए पर्याप्त नहीं हैं, तो यह काम नहीं कर सकता है, अगर स्पार्सिटी के बजाय संपीड़न आवंटित स्थान की मात्रा को कम कर रहा है।
स्टीफन चेज़लस

ज़रूर; SEEK_HOLEहालाँकि यह समस्याग्रस्त है, क्योंकि यह कई प्लेटफार्मों / फाइल सिस्टम द्वारा समर्थित नहीं है। लिनक्स में आप FIEMAP/ का भी उपयोग कर सकते हैं FIBMAP, लेकिन FIBMAPविशेष रूप से बहुत धीमी गति से है ... वहाँ एक अच्छा तरीका नहीं लगता है।
१४:१३

इसके अलावा इनमें से बहुत सारे तरीकों के लिए फाइल को पहले सिंक करने की आवश्यकता होती है।
फ्रॉस्ट्सचुट्ज़

धन्यवाद। हालांकि यह वास्तव में सवाल का जवाब नहीं देता है। मैं जाँच नहीं कर रहा हूँ कि क्या कोई विशेष फ़ाइल विरल है, लेकिन सिस्टम पर सभी स्पार्स फ़ाइलों को खोजने के लिए।
एंड्रयू फेरी

1
@AndrewFerrier माफ करना, मैं मैंने सोचा कि यह एक इस रैप करने के लिए तुच्छ पर्याप्त था लगता है कि for file in *या find। यदि आप किसी एकल फ़ाइल का परीक्षण कर सकते हैं, तो आप सभी फ़ाइलों का परीक्षण कर सकते हैं ... हालाँकि आपको इस पद्धति से निर्देशिकाओं को बाहर करना होगा।
फ्रॉस्ट्सचुट

3

स्टीफन चेज़लस के ऊपर दिए गए उत्तर में इस तथ्य पर ध्यान नहीं दिया गया है कि कुछ% स्पर्ज़ फाइल्स के साथ% S पैरामीटर रिपोर्ट की तरह अनुपात को इंगित करता है जैसे

9.31323e-09:./somedir/sparsefile.bin

इनके अतिरिक्त भी पाया जा सकता है

find . -type f ! -size 0 -printf '%S:%p\0' |
   sed -zn '/^\(0[^:]*:\)\|\([0-9.]\+e-.*:\)/p' |
   tr '\0' '\n'

1

एक संक्षिप्त स्क्रिप्ट जो मैंने यह जानने की कोशिश करते हुए लिखी थी कि किसी फ़ाइल में छेद के स्थान क्या हैं:

#!/usr/bin/python3
import os
import sys
import errno

def report(fname):
    fd = os.open(fname, os.O_RDONLY)
    len = os.lseek(fd, 0, os.SEEK_END)
    offset = 0
    while offset < len:
        start = os.lseek(fd, offset, os.SEEK_HOLE)
        if start == len:
            break
        try:
            offset = os.lseek(fd, start, os.SEEK_DATA)
        except OSError as e:
            if e.errno == errno.ENXIO:
                offset = len
            else:
                raise
        print(f'found hole between 0x{start:08X} and 0x{offset:08X} ({offset - start} bytes)')

if __name__ == '__main__':
    for name in sys.argv[1:]:
        report(name)

इस तरह से प्रिंट करता है सामान:

$ echo -n 'a' >zeros; truncate -s $((4096*4)) zeros; test/report-holes.py zeros
found hole between 0x00001000 and 0x00004000 (12288 bytes)

मेरे प्रश्न का उत्तर न दें क्योंकि मैं विरल फाइलों की तलाश में था, न कि किसी विशिष्ट फाइल के छिद्रों की, लेकिन फिर भी एक उपयोगी / प्रासंगिक स्क्रिप्ट। धन्यवाद। Upvoted।
एंड्रयू फेरियर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.