FileChecker...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich bastel gerade an einem kleinen FileChecker, der testet ob Dateien OK sind oder kaputt... Ich hab nämlich einige Dateien Bilder/Videos die offensichtlcih zerstört sind, weil sie leider nur noch aus Datenmüll bestehen. Diese will ich entdecken und löschen...

Zur Funktionsweise:
So gut wie jede Datei enthält einen immer gleichen Header, in dem bestimmte Strings immer vorkommen. Sind diese Strings nicht auffindbar, deutet das darauf hin, das die Datei nur noch Datenmüll ist...

Soweit hab ich auch schon eine grob Funktionstüchtige Variante fertig:
http://rafb.net/paste/results/t3ziye49.html

Das Prinzip:
In der Klasse FileInfoSave() sind die Daten hinterlegt, wie die HeaderInformation zu einem Dateityp aussehen:
Bsp.:
MyFileInfo.putFileInfo( "wav", "\A(RIFF).*?(WAVEfmt)", 16, "[('RIFF', 'WAVEfmt')]" )
MyFileInfo.putFileInfo( "exe", "\A(MZ)", 2 )

WAV-Dateien fangen immer mit "RIFF" an und haben in den ersten 16Bytes ein "WAVEfmt" stehen. In diesem Fall wird das re.findall() Ergebniss als String vorgegeben: "[('RIFF', 'WAVEfmt')]" Damit kann ich später, beim eigentlichen Checken einer WAV Datei einfach feststellen, ob die Datei in Odnung ist.

EXE-Dateien (Windows) fangen immer mit "MZ" an.


Und genau hier ist mein Problem.
Ich suche noch eine Sinnvolle Art und Weise die Header<->Dateityp Informationen abzuspeichern...

Anforderungen:
  • -Es kann verschiedene Endungen der selbe Dateityp existieren: .jpg .jpeg
    -Es sollte verschiendene Analysefunktionen geben: RE oder normaler Stringvergleich
    (z.B. die ersten 2Bytes bei EXE-Dateien = "MZ")
    -Das "Regelwerk" soll später gut lesbar/erweiterbar in eine Text-Datei
    -Zu jedem Dateityp soll noch eine kleine Beschreibung eingefügt werden
Und ich weiß nicht so recht, wie ich meine Klasse FileInfoSave() umschreiben kann, damit die Anforderungen erfüllt werden... Vorschläge?
BlackJack

Das klingt so ein bischen als wolltest Du das Programm 'file' nachprogrammieren. Hier ist eine Online-Version der man-Page mit dem Format der "magic" Datei, die die Regeln enthält nach denen 'file' Dateitypen erkennt:

http://www.die.net/doc/linux/man/man5/magic.5.html

Folgende Seite enthält auch ein kleines Beispiel:

http://www.mkssoftware.com/docs/man4/magic.4.asp
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

So ganz unrecht hast du nicht... Nur es soll unter Windows laufen ;)

Naja, ich weiß nur nicht so ganz wie ich die Daten organisieren soll, womit ich dann die Tests mache, ob eine Datei ok ist oder defekt...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

jens hat geschrieben:So ganz unrecht hast du nicht... Nur es soll unter Windows laufen ;)
Tut's doch.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Und falls Du es trotzdem in Python "nachbauen" möchtest, dann könntest Du vielleicht das "Magic"-File Format benutzen, damit bekommst Du im Netz genügend Daten um Dateitypen zu erkennen und musst die nicht selber schreiben.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ja, das wäre eine sehr gute Idee. Nur in wie weit sich die Informationen aus den Magic Dateien auslesen lassen, ist eine andere Sache.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Na mit open('/etc/magic', 'r'). Scherz beiseite: Einen Link zu einer man-Page, die das Format beschreibt, habe ich ja schon angegeben. Ist halt die Frage wie schwer das in Python umzusetzen ist.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Kann es sein, das dieses File nur für Ausführbare Dateien funktioniert???

Also ich bin mit meiner RE suche ja ganz zufrieden, weil es funktioniert... Ich weiß nur nicht, wie ich am besten das Regelwerk speichere:
MyFileInfo.putFileInfo( "wav", "\A(RIFF).*?(WAVEfmt)", 16, "[('RIFF', 'WAVEfmt')]" )
MyFileInfo.putFileInfo( "exe", "\A(MZ)", 2 )

WAV-Dateien fangen immer mit "RIFF" an und haben in den ersten 16Bytes ein "WAVEfmt" stehen. In diesem Fall wird das re.findall() Ergebniss als String vorgegeben: "[('RIFF', 'WAVEfmt')]" Damit kann ich später, beim eigentlichen Checken einer WAV Datei einfach feststellen, ob die Datei in Odnung ist.
BlackJack

jens hat geschrieben:Kann es sein, das dieses File nur für Ausführbare Dateien funktioniert???
Du meinst das (Unix)Programm 'file'? Nein, wie kommst Du da drauf?

Code: Alles auswählen

bj@s8n:~> file CoArray_Python.pdf
CoArray_Python.pdf: PDF document, version 1.4
bj@s8n:~> file emptybox.png
emptybox.png: PNG image data, 640 x 480, 8-bit/color RGB, non-interlaced
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

jens hat geschrieben:Kann es sein, das dieses File nur für Ausführbare Dateien funktioniert???
Dann hätte es ja wohl kaum Sinn. Nein, das geht für alle Dateien.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

BlackJack hat geschrieben:Das klingt so ein bischen als wolltest Du das Programm 'file' nachprogrammieren.
Das scheint auf jeden Fall nicht nötig zu sein... Es gibt einen Python-Wrapper... Hier eine README Auszug:
This directory contains Python bindings to allow you to access the
libmagic api. At the moment their status is "experimental" and
they are not built by default. You may need to edit include and library
search paths in setup.py so that python's distutils build process can
find the magic header and lib files.
[...]
Das ganze liegt in .\GnuWin32\src\file\4.13\file-4.13-src\python

Das benutzen ist auch recht einfach:

Code: Alles auswählen

import magic

ms = magic.open(magic.MAGIC_NONE)
ms.load()
type =  ms.file("/path/to/some/file")
print type

f = file("/path/to/some/file", "r")
buffer = f.read(4096)
f.close()

type = ms.buffer(buffer)
print type

ms.close()
Getestet hab ich's aber noch nicht...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten