Menemukan file jarang?


19

Apakah ada cara mudah untuk menemukan semua file jarang di sistem saya, atau di pohon direktori tertentu?

Jika relevan, saya menggunakan zshUbuntu 12.04, meskipun jawaban Unix-y yang lebih umum untuk bash / sh, misalnya, akan baik-baik saja.

Sunting : untuk memperjelas, saya mencari untuk mencari file yang jarang, tidak memeriksa status jarangnya dari satu file.



2
Apa yang membuat Anda merasa mencari file jarang tidak termasuk memeriksa status jarangnya masing-masing?
jlliagre

Jawaban:


11

Pada sistem (dan sistem file) yang mendukung SEEK_HOLE lseekflag (seperti Ubuntu 12.04 Anda pada ext4 akan) dan dengan asumsi nilai SEEK_HOLEadalah 4 seperti di Linux:

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

Sintaks shell itu adalah POSIX. Hal-hal non-portabel di dalamnya adalah perldan itu SEEK_HOLE.

lseek(SEEK_HOLE)mencari ke awal lubang pertama di file, atau akhir file jika tidak ada lubang yang ditemukan. Di atas kita tahu file tidak jarang ketika lseek(SEEK_HOLE)membawa kita ke akhir file (ke tempat yang sama dengan lseek(SEEK_END)).

Jika Anda ingin membuat daftar file yang jarang:

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(sejak versi 4.3.3) harus -printf %Smelaporkan jarangnya file. Dibutuhkan pendekatan yang sama dengan jawaban frostschutz karena dibutuhkan rasio penggunaan disk vs ukuran file, jadi tidak dijamin untuk melaporkan semua file jarang (seperti ketika ada kompresi pada tingkat filesystem atau di mana ruang yang disimpan oleh lubang tidak mengkompensasi overhead infrastruktur sistem file atau atribut diperluas besar), tetapi akan bekerja pada sistem yang tidak memiliki SEEK_HOLEatau sistem file di mana SEEK_HOLEtidak diimplementasikan. Di sini dengan alat GNU:

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

(perhatikan bahwa versi sebelumnya dari jawaban ini tidak berfungsi dengan baik ketika findmenyatakan sparseness seperti misalnya 3.2e-05. Terima kasih atas jawaban @ flashydave untuk membawanya ke perhatian saya)


Komentar yang sama seperti di atas; Saya sedang mencari cara untuk menemukan semua file yang jarang, tidak memeriksa file tertentu.
Andrew Ferrier

1
Mungkin findjuga harus mengecualikan 0-byte-file sekaligus?
frostschutz

@ frostschutz, poin bagus, jawaban diperbarui.
Stéphane Chazelas

Nice ditemukan dengan find -printf '%S'! :-)
frostschutz

1
@ Brian, ganti trperintah denganxargs -r0 rm -f
Stéphane Chazelas

8

File biasanya jarang ketika jumlah blok yang dialokasikan lebih kecil dari ukuran file (di sini menggunakan GNU statseperti yang ditemukan di Ubuntu, tetapi berhati-hatilah sistem lain mungkin memiliki implementasi yang tidak kompatibel stat).

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

Varian dengan find: (dicuri dari Stephane)

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

Anda biasanya meletakkan ini dalam skrip shell, kemudian mengeksekusi skrip shell.

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

Itu mungkin tidak berfungsi jika blok jarang tidak cukup untuk menutupi overhead dari blok tidak langsung dalam sistem file tradisional misalnya, jika kompresi bukannya kekeringan mengurangi jumlah ruang yang dialokasikan.
Stéphane Chazelas

Tentu; SEEK_HOLEsama bermasalahnya, karena tidak didukung oleh banyak platform / sistem file. Di Linux Anda juga bisa menggunakan FIEMAP/ FIBMAP, tetapi FIBMAPkhususnya sangat lambat ... sepertinya tidak ada cara yang baik.
frostschutz

Juga banyak dari metode ini memerlukan file untuk disinkronkan terlebih dahulu.
frostschutz

Terima kasih. Tapi itu tidak benar-benar menjawab pertanyaan. Saya tidak ingin memeriksa apakah file tertentu jarang, tetapi untuk menemukan semua file jarang pada sistem.
Andrew Ferrier

1
@AndrewFerrier maaf, saya kira saya pikir itu cukup sepele untuk membungkus ini dalam for file in *atau find. Jika Anda dapat menguji satu file, Anda dapat menguji semua file ... walaupun Anda harus mengecualikan direktori dengan metode ini.
frostschutz

3

Stephane Chazelas jawaban di atas tidak memperhitungkan fakta bahwa beberapa file jarang dengan parameter% S melaporkan rasio sebagai angka floating point seperti

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

Ini dapat ditemukan di samping dengan

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

1

Sebuah skrip pendek yang saya tulis ketika mencoba mencari tahu apa lokasi lubang dalam sebuah file:

#!/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)

Ini mencetak hal-hal seperti:

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

Tidak menjawab pertanyaan saya karena saya mencari file yang jarang, bukan lubang di file tertentu, tetapi masih berupa skrip yang berguna / relevan. Terima kasih. Terpilih.
Andrew Ferrier
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.