Ich bin es leid, immer die Dateien für mein Backup, das mittlerweile mehrere DVDs umfasst, manuell auf die DVDs zu verteilen, um den Platz möglichst effektiv zu nutzen. Ich möchte deshalb ein Python-Script dafür erstellen. Dabei stellen sich mir 2 Probleme:
1. Alle Möglichkeiten zu berechnen, um mehrere Hundert Dateien auf 3 bis 4 DVDs zu verteilen, dürfte kaum möglich sein (schon 3^1000 ist nicht mehr zu bewältigen). Gibt es für so etwas bekannte Algorithmen?
2. Gibt es ein Command-Line-Tool oder ein über die Command-Line zu steuerndes GUI-Programm zum Brennen von DVDs unter Windows? Mir sind zwar mkisofs und cdrecord von Linux bekannt; da ich aber unter Windows arbeite, müsste ich diese dann wieder über cyqwin oder mingw laufen lassen, was ich ungern tuen würde.
Danke
HWK
Datei-Backup optimieren
Du könntest die Dateien rar'en und dabei mit -v die Dateigröße der einzelnen Rarteile angeben oder du speicherst (Größe / Pfad) in einer Liste (whatever) und suchst dir so die Dateien raus, dass du möglichst nah an 4,4GB kommst. Das dürfte mit einigen Hundert Dateien zu machen sein.
Apropos: Gib mal 3**1000 in den Interpreter ein. Einige Hundert!?
Apropos: Gib mal 3**1000 in den Interpreter ein. Einige Hundert!?
Ich möchte möglichst kein Archiv speichern. Die Performance, aus einem 4,5 GByte großen Archiv eine Datei wiederzuladen, dürfte wohl relativ schlecht sein. Was ist, wenn das Archiv beschädigt ist? Möglicherweise sind dann alle Dateien nicht mehr zu lesen. Auch das Erstellen des Archivs selbst dürfte schon einige Zeit benötigen.
Mehrere Hundert bezog sich auf die Anzahl der zu speichernden Dateien. Dass 3^1000, d.h. die Zahl der Möglichkeiten, um 1000 Dateien auf 3 DVDs zu verteilen, nicht mehr zu bewältigen ist, also wesentlich größer als einige Hundert ist, sagte ich ja bereits selbst.
Trotzdem Danke für den Vorschlag.
MfG
HWK
Mehrere Hundert bezog sich auf die Anzahl der zu speichernden Dateien. Dass 3^1000, d.h. die Zahl der Möglichkeiten, um 1000 Dateien auf 3 DVDs zu verteilen, nicht mehr zu bewältigen ist, also wesentlich größer als einige Hundert ist, sagte ich ja bereits selbst.
Trotzdem Danke für den Vorschlag.
MfG
HWK
zu 2.: Die beiden Windows-Brennprogramme burnatonce und InfraRecorder bringen bereits als .exe kompilierte Versionen dieser Tools mit, die du so benutzen können solltest. Vielleicht hilft dir das ja bereits.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo Panke!Panke hat geschrieben:Du könntest die Dateien rar'en
Wir haben lange Zeit RAR für Datensicherungen eingesetzt. Ich möchte jedem davon dringendst abraten. RAR braucht im Schnitt sieben (7) bis zehn (10) mal länger für die gleiche Datenmenge als ZIP. Schlimm wird es dann, wenn die Server am nächsten Vormittag immer noch beim Komprimieren der Sicherungen sind.
Wir haben darauf hin ein paar Tests gemacht und RAR, ZIP, BZIP2 und GZIP miteinander verglichen. GZIP arbeitet am Schnellsten und komprimiert dabei genügend gut. RAR und BZIP2 komprimieren ein bischen besser, brauchen aber dafür **viel mehr** Zeit. Dieses "bischen Besser" ist den Zeitaufwand nicht Wert.
mfg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
@YOGi: Danke für die Tips. Es scheinen aber beides Programme zu sein, die Windows-Oberflächen für die bekannten Linux-cdrtools erzeugen, so dass ich wieder cygwin verwenden muss. Wie gesagt möchte ich dies aber möglichst nicht.
@Gerold: Hälst Du es denn für sinnvoll, Pankes Vorschlag mit einem Deiner bevorzugten Komprimierer umzusetzen? Kann man mit GZIP z.B. ein riesiges Archiv auf mehrere DVDs verteilen?
Wie sieht es dann mit meinen o.g. Bedenken aus: Kann ich aus einem beschädigten Archiv noch einzelne Dateien restaurieren? Braucht das Zurückladen einzelner Dateien nicht sehr viel Zeit und Festplattenspeicher? Das Komprimieren an sich wäre für mich nebensächlich, da die meisten Dateien schon komprimiert sind.
MfG
HWK
@Gerold: Hälst Du es denn für sinnvoll, Pankes Vorschlag mit einem Deiner bevorzugten Komprimierer umzusetzen? Kann man mit GZIP z.B. ein riesiges Archiv auf mehrere DVDs verteilen?
Wie sieht es dann mit meinen o.g. Bedenken aus: Kann ich aus einem beschädigten Archiv noch einzelne Dateien restaurieren? Braucht das Zurückladen einzelner Dateien nicht sehr viel Zeit und Festplattenspeicher? Das Komprimieren an sich wäre für mich nebensächlich, da die meisten Dateien schon komprimiert sind.
MfG
HWK
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo Panke!Panke hat geschrieben:Splittet mir gzip die Volumens automatisch? Oder muss ich da vorher ein Tar-Script schreiben?
GZIP ist ein reines Kompressionsprogramm. Eine Datei oder ein Datenstream kann damit komprimiert werden. Es ist also nicht dafür geeignet, mehrere Dateien zu komprimieren. Dafür ist TAR vorgesehen. TAR komprimiert von sich aus die Daten mit GZIP, wenn man den Parameter "-z" verwendet.
TAR komprimiert aber erst nach dem Splitten. Deshalb verwende ich für so etwas lieber das Programm DAR http://dar.linux.free.fr/
DAR komprimiert zuerst mit GZIP und splittet erst danach. DAR ist so oder so ein Geheimtipp.
mfg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Kommt auf das Archiv an. Bei ZIP ist es kein Problem gezielt auf eine Datei zuzugreifen.HWK hat geschrieben:Ich möchte möglichst kein Archiv speichern. Die Performance, aus einem 4,5 GByte großen Archiv eine Datei wiederzuladen, dürfte wohl relativ schlecht sein.
Das kommt auch wieder auf das Archiv an.Was ist, wenn das Archiv beschädigt ist? Möglicherweise sind dann alle Dateien nicht mehr zu lesen.
Ich benutze `tar.bz2` und sichere die Datenträger mit dvdisaster ab. Wenn man öfter auf einzelne Dateien aus der Sicherungskopie zugreifen muss, ist `tar.bz2` natürlich langsamer als ein ZIP-Archiv oder die Dateien direkt auf den Datenträger zu sichern. Das ist aber auch nicht das Szenario gegen dass ich mich absichern möchte. Mir geht's weniger um Einzeldateien, sondern mehr um kaputte Platten. Die zwei bis dreimal im Jahr, die ich gerne einzelne Dateien wiederhaben möchte, kann ich auch ein wenig warten.
Das kommt, wie Gerold schon schrieb, auf die Komprimierung an. Der "deflate"-Algorithmus, der bei ZIP-Archiven und von `gzip` benutzt wird, ist recht schnell. Da stehen die Chancen gut, dass bei einem aktuellen Rechner die Rechenzeit kleiner, oder zumindest nicht wesentlich höher ist, als die Zeit, die auf die Platte gewartet werden muss.Auch das Erstellen des Archivs selbst dürfte schon einige Zeit benötigen.
Falls das immer noch nicht schnell genug ist, gibt's noch lzop. Angeblich das schnellste (De)Komprimierungsprogramm, wobei die Kompressionsrate nur ein wenig schlechter als beim "deflate"-Algorithmus ist.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo HWK!HWK hat geschrieben:@Gerold: Hälst Du es denn für sinnvoll, Pankes Vorschlag mit einem Deiner bevorzugten Komprimierer umzusetzen?
Leider sind meine Vorschläge keine Lösung für dein Problem. Ich bin mir sicher, dass es für dein Problem fix und fertige Algorithmen gib.
Ich persönlich, würde mir die Suche danach aber gar nicht erst antun. Wenn du in einer Liste alle Dateinamen mit deren Größen hälst und diese nach Größe (absteigend) sortierst, dann kannst du diese Liste der Reihe nach abarbeiten. Das schließt zwar nicht aus, dass auf einer CD mehr und auf der anderen weniger drauf ist, aber du sparst dir dadurch das Durchrechnen aller Möglichkeiten.
Vielleicht so:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
from pprint import pprint
MAX_SIZE = 400000
def main():
filelist = [
[1000, "C:\\ordner1\\dateix.txt"],
[51000, "C:\\ordner1\\dateiy.txt"],
[100, "C:\\ordner1\\dateiu.txt"],
[370000, "C:\\ordner1\\datei1.txt"],
[770000, "C:\\ordner1\\i_am_to_large.txt"],
[156000, "C:\\ordner1\\datei2.txt"],
[61800, "C:\\ordner1\\datei3.txt"],
[70000, "C:\\ordner1\\datei4.txt"],
[175451, "C:\\ordner1\\datei5.txt"],
[15783, "C:\\ordner1\\datei6.txt"],
]
filelist.sort(reverse = True)
destlist = []
to_large = []
for source_size, source_filename in filelist:
if source_size > MAX_SIZE:
to_large.append(source_filename)
continue
for index, (dest_size, dest_items) in enumerate(destlist):
if (dest_size + source_size) <= MAX_SIZE:
destlist[index][0] = dest_size + source_size
dest_items.append(source_filename)
break
else:
destlist.append([source_size, [source_filename]])
pprint(destlist)
pprint(to_large)
if __name__ == "__main__":
main()
Code: Alles auswählen
[[386883,
['C:\\ordner1\\datei1.txt',
'C:\\ordner1\\datei6.txt',
'C:\\ordner1\\dateix.txt',
'C:\\ordner1\\dateiu.txt']],
[393251,
['C:\\ordner1\\datei5.txt',
'C:\\ordner1\\datei2.txt',
'C:\\ordner1\\datei3.txt']],
[121000, ['C:\\ordner1\\datei4.txt', 'C:\\ordner1\\dateiy.txt']]]
['C:\\ordner1\\i_am_to_large.txt']
Gerold
Zuletzt geändert von gerold am Sonntag 8. Juli 2007, 11:47, insgesamt 2-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
@BlackJack: dvdisaster ist ein guter Tip. Der zusätzliche Speicherbedarf von ca. 15% ist aber natürlich ziemlich heftig.
Noch eine Frage zum Verständnis: Wenn ich aus einem ZIP-Archiv eine einzelne Datei zurückladen will, muss dann erst das gesamte Verzeichnis von der DVD geladen werden?
Eine weitere rein informative Frage: Ist es notwendig oder zumindest sinnvoll, nach dem Brennen des Backups den Inhalt der DVD mit dem Original zu vergleichen, was ja die Backup-Zeit verdoppelt?
MfG
HWK
Noch eine Frage zum Verständnis: Wenn ich aus einem ZIP-Archiv eine einzelne Datei zurückladen will, muss dann erst das gesamte Verzeichnis von der DVD geladen werden?
Eine weitere rein informative Frage: Ist es notwendig oder zumindest sinnvoll, nach dem Brennen des Backups den Inhalt der DVD mit dem Original zu vergleichen, was ja die Backup-Zeit verdoppelt?
MfG
HWK
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo HWK!HWK hat geschrieben:Ist es notwendig oder zumindest sinnvoll, nach dem Brennen des Backups den Inhalt der DVD mit dem Original zu vergleichen, was ja die Backup-Zeit verdoppelt?
Ich empfinde das Brennen auf DVDs als Glücksspiel. Ein geringer Datenverlust ist bei einem Video nicht merkbar. Aber in einer wichtigen Datendatei ist eine 0 statt einer 1 eine Katastrophe. So ungeduldig kann ich gar nicht sein, dass ich die Daten der gebrannten DVD nach dem Brennen nicht vergleiche. Komisch ist nur, dass es noch nie einen Fehler auf DVD gab, seit ich die Daten verifiziere. Aber Murphy ist überall.
mfg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
@HWK: Auf Dateien in einer ZIP-Datei kann man direkt zugreifen. Im ZIP ist ein Inhaltsverzeichnis mit den Dateinamen und dem Offset innerhalb des Archivs gespeichert.
@gerold: Direkt nach dem brennen von DVDs habe ich auch noch nie einen Fehler gehabt, ausser das Brennprogramm hat schon gemeckert. Bei Rohlingen wo die Brenner-Firmware wohl nicht die idealen Einstellungen kannte, fing der Datenverlust aber schon mal nach ein paar Tagen an und wurde dann immer schlimmer.
Ich benutze jetzt immer die gleiche Rohlingsmarke und teste die Sicherungskopien zwei Tage nach dem brennen noch einmal. Dabei ist bis jetzt noch kein Fehler aufgetreten. Aber Du erwähntest Murphy ja schon.
@gerold: Direkt nach dem brennen von DVDs habe ich auch noch nie einen Fehler gehabt, ausser das Brennprogramm hat schon gemeckert. Bei Rohlingen wo die Brenner-Firmware wohl nicht die idealen Einstellungen kannte, fing der Datenverlust aber schon mal nach ein paar Tagen an und wurde dann immer schlimmer.
Ich benutze jetzt immer die gleiche Rohlingsmarke und teste die Sicherungskopien zwei Tage nach dem brennen noch einmal. Dabei ist bis jetzt noch kein Fehler aufgetreten. Aber Du erwähntest Murphy ja schon.
Bei mir sind das Kommandozeilen-Tools, die sich möglicherweise der mitgelieferten cygwin1.dll bedienen, aber das war's auch schon. Das ist unabhängig und über `subprocess` sicher problemlos benutzbar.HWK hat geschrieben:@YOGi: Danke für die Tips. Es scheinen aber beides Programme zu sein, die Windows-Oberflächen für die bekannten Linux-cdrtools erzeugen, so dass ich wieder cygwin verwenden muss. Wie gesagt möchte ich dies aber möglichst nicht.
Zu den Archiven: RAR gefällt mir ganz und gar nicht, weil nur der Algorithmus zur Dekompression offen gelegt ist, der zur Kompression aber nicht. So einem Format werde ich daher keine Daten anvertrauen - schon gar nicht wichtige Backups oder Archive, die über viele Jahre wichtige Daten beherbergen sollen.
7-Zip (.7z) möchte ich noch nennen. Es hat eine sehr hohe Kompressionsrate, ist aber wie Bzip2 dann auch länger dabei.
Über letzteres meine ich zudem mal gelesen zu haben, dass die entpackte Datengröße aus dem Archiv selbst nicht abgeleitet werden kann. In dem Zusammenhang sind wohl auch mal "Archivbomben" für Virenscanner aufgetaucht, die nur wenige Kilo- oder Megabyte große Bzip2-Archive waren, sich aber auf mehrere Gigabyte entpackten.
Zum Thema Anfälligkeit von Archiven sei auch das Schlagwort "Solid (Archive)" genannt. Dazu aus der Wikipedia-Seite zu RAR:
Ein Blick in die englische Wikipedia zu den gängigen Formaten ist ebenfalls zu empfehlen, weil dort oft mehr und bessere Information vorliegt.Durch die Technik der progressiven bzw. Solid-Archivierung (Solid Mode bzw. Solid Archiving Technique) werden die ausgewählten Dateien nicht einzeln, sondern alle zusammen komprimiert. Dieses Verfahren findet sein Vorbild in komprimierten Tarballs.
Der Vorteil besteht darin, dass Redundanzen zwischen mehreren Dateien auch eliminiert werden können, was bei vielen kleineren gleichartigen Dateien den größten Effekt entfaltet. Außerdem brauchen so weniger formatspezifische Informationen gespeichert zu werden. Der Nachteil besteht in der Fehleranfälligkeit des gepackten Archivs, da es als Ganzes intakt sein muss, um einzelne Dateien zu extrahieren. Um diesen Nachteil etwas auszugleichen kann ein sogenannter Recovery Record mitabgespeichert werden, mit dem fehlerhafte RAR-Archive gegebenenfalls in begrenztem Umfang repariert werden können.
@Gerold: Danke für Dein Beispiel. Ich tendiere jetzt aber zu einer anderen Lösung. Meine zu sichernden Dateien befinden sich in mehreren Ordnern. Um nicht völliges Chaos auf den Backup-Medien zu erhalten, wäre es sowieso schön, möglichst einen kompletten Ordner auf das Medium zu brennen. Ich muss dann also nur noch die Ordner auf die DVDs verteilen. Das sind aber nicht so viele, dass ich nicht alle Möglichkeiten durchprobieren könnte. Der verschenkte Platz wird dadurch aber natürlich größer.
MfG
HWK
EDIT: So kann man sich täuschen: Es handelte sich dann doch um 91 Ordner. Somit waren trotz verschiedener Optimierungsversuche natürlich nicht alle Varianten zu berechnen. Ich habe dann doch Deine ja mittlerweile noch verbesserte Version implementiert und siehe da:
Auf 4 DVDs verteilt werden bei den ersten 3 DVDs nicht einmal 0,5 MByte verschenkt. Das ist doch wohl eine gute Ausbeute.
Ein bisschen habe ich Deinen Code allerdings geändert, weil mich das enumerate gestört hat:Somit nochmals vielen Dank Gerold.
MfG
HWK
EDIT: So kann man sich täuschen: Es handelte sich dann doch um 91 Ordner. Somit waren trotz verschiedener Optimierungsversuche natürlich nicht alle Varianten zu berechnen. Ich habe dann doch Deine ja mittlerweile noch verbesserte Version implementiert und siehe da:
Auf 4 DVDs verteilt werden bei den ersten 3 DVDs nicht einmal 0,5 MByte verschenkt. Das ist doch wohl eine gute Ausbeute.
Ein bisschen habe ich Deinen Code allerdings geändert, weil mich das enumerate gestört hat:
Code: Alles auswählen
def divide(dir_list):
'''Verzeichnisse auf mehrere DVDs verteilen.'''
dir_list.sort(reverse=True)
dest_list = []
to_large = []
for source_size, source_filename in dir_list:
if source_size > MAXSIZE:
to_large.append(source_filename)
continue
for dest_size, dest_items in dest_list:
if (dest_size[0] + source_size) <= MAXSIZE:
dest_size[0] += source_size
dest_items.append(source_filename)
break
else:
dest_list.append([[source_size], [source_filename]])
return dest_list, to_large
So, das ist jetzt mein weitgehend fertiges Backup-Programm. Zum Brennen habe ich letztendlich Nero verwendet. Dies liegt ja vielen Brennern bei und kann mit nerocmd über die Kommandozeile gesteuert werden.Die zu sichernden Dateien bzw. Ordner befinden sich in einer Datei names Dirs.txt. Der Parameter 'S' am Ende führt dazu, dass die darin enthaltenen Ordner/Dateien einzeln erfasst werden. Das kürzt die Eingabe ab. dirsize berechnet die Größe eines Verzeichnisses. divide entspricht weitgehend Gerolds Script.
MfG
HWK
Code: Alles auswählen
#!/usr/local/bin/python
# -*- coding: cp1252 -*-
# File: Backup.py
'''Script zum optimierten Backup auf mehrere Medien.'''
import os
DIRFILE = 'Dirs.txt'
MAXSIZE = 4700000000
NEROCMD = 'c:\\programme\\nero\\"nero 7"\\Core\\nerocmd.exe --write '\
'--drivename d --real --speed 04 --iso Backup.%03i --dvd '\
'--detect_non_empty_disc --enable_abort --underrun_prot '\
'--create_iso_fs --recursive --disable_eject --verify "%s"'
#' --force_erase_disc'
def dirsize(name):
'''Größe eines Verzeichnisses bestimmen.'''
if not os.path.exists(name):
return -1
if os.path.isfile(name):
return os.path.getsize(name)
size = 0
for path, dirs, files in os.walk(name):
for dir_ in dirs:
size += os.path.getsize(os.path.join(path, dir_))
for file_ in files:
size += os.path.getsize(os.path.join(path, file_))
return size
def make_dir_list():
'''Liste der Verzeichnisse und deren Größe erstellen.'''
dir_list = []
try:
infile = file(DIRFILE, 'r')
try:
for name in infile:
name = name.strip()
if name.endswith(' S'):
name = name[:-2]
if os.path.isdir(name):
for name_ in os.listdir(name):
name_ = os.path.join(name, name_)
size = dirsize(name_)
if size >= 0:
dir_list.append((size, name_))
continue
size = dirsize(name)
if size >= 0:
dir_list.append((size, name))
finally:
infile.close()
except IOError, error:
print 'Kann Datei "%s" nicht lesen!' % DIRFILE
return dir_list
def divide(dir_list):
'''Verzeichnisse auf mehrere Medien verteilen.'''
dir_list.sort(reverse=True)
dest_list = []
to_large = []
for source_size, source_filename in dir_list:
if source_size > MAXSIZE:
to_large.append(source_filename)
continue
for dest_size, dest_items in dest_list:
if (dest_size[0] + source_size) <= MAXSIZE:
dest_size[0] += source_size
dest_items.append(source_filename)
break
else:
dest_list.append([[source_size], [source_filename]])
return dest_list, to_large
def main():
dir_list = make_dir_list()
if not dir_list:
return
cont, to_large = divide(dir_list)
if to_large:
print 'Zu groß für ein Medium sind:\n%s' % (', '.join(to_large))
for i, (size, cont_) in enumerate(cont):
print 'Schreibe Medium Nr. %i' % (i + 1)
os.system(NEROCMD % (i + 1, '" "'.join(cont_)))
if __name__ == '__main__':
main()
MfG
HWK