Suchen Sie spärliche Dateien?


19

Gibt es eine einfache Möglichkeit, alle Dateien mit geringer Dichte auf meinem System oder in einem bestimmten Verzeichnisbaum zu finden?

Wenn es relevant ist, verwende ich zshUbuntu 12.04, obwohl eine allgemeinere Unix-y-Antwort zum Beispiel für bash / sh in Ordnung wäre.

Bearbeiten : Um dies zu verdeutlichen, suche ich nach Dateien mit geringer Dichte und überprüfe nicht den Status einer einzelnen Datei.



2
Bei der Suche nach Dateien mit geringer Dichte müssen Sie nicht den Status einzelner Dateien überprüfen.
Juli

Antworten:


11

Auf Systemen (und Dateisystemen), die das SEEK_HOLE lseekFlag unterstützen (wie bei Ubuntu 12.04 unter ext4) und den Wert SEEK_HOLE4 annehmen, wie dies unter Linux der Fall ist:

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

Diese Shell-Syntax lautet POSIX. Die nicht tragbaren Dinge darin sind perlund das SEEK_HOLE.

lseek(SEEK_HOLE)Sucht nach dem Anfang des ersten Lochs in der Datei oder nach dem Ende der Datei, wenn kein Loch gefunden wird. Oben wissen wir, dass die Datei nicht spärlich ist, wenn sie lseek(SEEK_HOLE)uns zum Ende der Datei führt (an die gleiche Stelle wie lseek(SEEK_END)).

Wenn Sie die Sparse-Dateien auflisten möchten:

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

Die GNU find(seit Version 4.3.3) muss -printf %Sdie Kargheit einer Datei melden . Dies entspricht dem Ansatz von frostschutz, bei dem das Verhältnis von Datenträgernutzung zu Dateigröße berücksichtigt wird. Es kann daher nicht garantiert werden, dass alle Dateien mit geringer Speicherkapazität gemeldet werden (z. B. wenn die Komprimierung auf Dateisystemebene erfolgt oder der durch die Lücken gespeicherte Speicherplatz nicht Kompensieren Sie den Overhead der Dateisysteminfrastruktur (oder große erweiterte Attribute), funktionieren Sie jedoch auf Systemen ohne SEEK_HOLEoder auf Dateisystemen, auf denen dies SEEK_HOLEnicht implementiert ist. Hier mit GNU-Tools:

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

(Beachten Sie, dass eine frühere Version dieser Antwort nicht richtig funktionierte, wenn finddie Kargheit ausgedrückt wurde, wie zum Beispiel 3.2e-05. Vielen Dank an @ flashydaves Antwort , dass Sie mich darauf aufmerksam gemacht haben.)


Gleicher Kommentar wie oben; Ich suche nach einer Möglichkeit, alle Dateien mit geringer Dichte zu finden, und nicht nach einer bestimmten Datei.
Andrew Ferrier

1
Vielleicht findsollte man auch 0-Byte-Dateien komplett ausschließen?
Frostschutz

@ Frostschutz, guter Punkt, Antwort aktualisiert.
Stéphane Chazelas

Schöner Fund mit dem find -printf '%S'! :-)
Frostschutz

1
@ Brian, ersetze den trBefehl durchxargs -r0 rm -f
Stéphane Chazelas

8

Eine Datei ist normalerweise sparsam, wenn die Anzahl der zugewiesenen Blöcke kleiner als die Dateigröße ist (hier unter Verwendung von GNU, statwie es unter Ubuntu zu finden ist, aber beachten Sie, dass andere Systeme möglicherweise nicht kompatible Implementierungen von haben stat).

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

Variante mit find: (von Stephane gestohlen)

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

Sie würden dies normalerweise in ein Shell-Skript schreiben und dann das Shell-Skript ausführen.

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

Dies funktioniert möglicherweise nicht, wenn die spärlichen Blöcke nicht ausreichen, um den Overhead indirekter Blöcke in herkömmlichen Dateisystemen zu decken, z.
Stéphane Chazelas

Sicher; SEEK_HOLEist jedoch genauso problematisch, da es von vielen Plattformen / Dateisystemen nicht unterstützt wird. In Linux könnte man auch FIEMAP/ verwenden FIBMAP, aber FIBMAPinsbesondere ist es furchtbar langsam ... es scheint einfach keinen guten Weg zu geben.
Frostschutz

Bei vielen dieser Methoden muss die Datei zuerst synchronisiert werden.
Frostschutz

Vielen Dank. Das beantwortet die Frage allerdings nicht wirklich. Ich möchte nicht überprüfen, ob eine bestimmte Datei dünn ist, sondern alle dünn besetzten Dateien auf dem System finden.
Andrew Ferrier

1
@ AndrewFerrier Entschuldigung, ich glaube, ich dachte, es wäre trivial genug, dies in ein for file in *oder zu packen find. Wenn Sie eine einzelne Datei testen können, können Sie alle Dateien testen, obwohl Sie mit dieser Methode Verzeichnisse ausschließen müssen.
Frostschutz

3

Die obige Antwort von Stephane Chazelas berücksichtigt nicht die Tatsache, dass einige spärliche Dateien mit dem Parameter find% S das Verhältnis als Gleitkommazahlen wie angeben

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

Diese finden Sie zusätzlich bei

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

1

Ein kurzes Skript, das ich geschrieben habe, als ich versucht habe, die Position der Löcher in einer Datei herauszufinden:

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

Dies druckt Sachen wie:

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

Beantwortet meine Frage nicht, da ich nach spärlichen Dateien gesucht habe, nicht nach Lücken in einer bestimmten Datei, sondern nach einem nützlichen / relevanten Skript. Vielen Dank. Upvoted.
Andrew Ferrier
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.