
Ich habe vor einiger Zeit zwei Rettungsversuche auf einer sterbenden Festplatte unternommen. ddrescue
Zuerst habe ich (GNU) ausgeführt und dann direkt dd
mit manueller Suche. Ich möchte das Beste aus beiden Bildern herausholen. Da alle leeren Abschnitte in den Dateien nur Nullen sind, sollte ein bitweises UND ausreichen, um die beiden Dateien zusammenzuführen.
Gibt es ein Dienstprogramm, mit dem ich eine Datei erstellen kann, die das ODER zweier Eingabedateien ist?
(Ich verwende ArchLinux, aber ich installiere gerne aus dem Quellcode, wenn dieser nicht in den Repos enthalten ist.)
Antwort1
Ich kenne kein Dienstprogramm, das dies kann, aber es sollte ziemlich einfach sein, ein Programm dafür zu schreiben. Hier ist ein grobes Beispiel in Python:
#!/usr/bin/env python
f=open("/path/to/image1","rb")
g=open("/path/to/image2","rb")
h=open("/path/to/imageMerge","wb") #Output file
while True:
data1=f.read(1) #Read a byte
data2=g.read(1) #Read a byte
if (data1 and data2): #Check that neither file has ended
h.write(chr(ord(data1) | ord(data2))) #Or the bytes
elif (data1): #If image1 is longer, clean up
h.write(data1)
data1=f.read()
h.write(data1)
break
elif (data2): #If image2 is longer, clean up
h.write(data2)
data2=g.read()
h.write(data2)
break
else: #No cleanup needed if images are same length
break
f.close()
g.close()
h.close()
Oder ein C-Programm, das schneller laufen sollte (bei dem aber die Wahrscheinlichkeit eines unbemerkten Fehlers deutlich höher ist):
#include <stdio.h>
#include <string.h>
#define BS 1024
int main() {
FILE *f1,*f2,*fout;
size_t bs1,bs2;
f1=fopen("image1","r");
f2=fopen("image2","r");
fout=fopen("imageMerge","w");
if(!(f1 && f2 && fout))
return 1;
char buffer1[BS];
char buffer2[BS];
char bufferout[BS];
while(1) {
bs1=fread(buffer1,1,BS,f1); //Read files to buffers, BS bytes at a time
bs2=fread(buffer2,1,BS,f2);
size_t x;
for(x=0;bs1 && bs2;--bs1,--bs2,++x) //If we have data in both,
bufferout[x]=buffer1[x] | buffer2[x]; //write OR of the two to output buffer
memcpy(bufferout+x,buffer1+x,bs1); //If bs1 is longer, copy the rest to the output buffer
memcpy(bufferout+x,buffer2+x,bs2); //If bs2 is longer, copy the rest to the output buffer
x+=bs1+bs2;
fwrite(bufferout,1,x,fout);
if(x!=BS)
break;
}
}
Antwort2
Python
with open('file1', 'rb') as in1, open('file2', 'rb') as in2, open('outfile', 'wb') as out:
while True:
bytes1 = in1.read(1024)
bytes2 = in2.read(1024)
if not bytes1 or not bytes2:
break
out.write(bytes(b1 | b2 for (b1, b2) in zip(bytes1, bytes2)))
Dies ist etwa 10-mal schneller als Chris' Python-Lösung, da 1024 Bytes auf einmal gelesen werden. Außerdem wird das with open
Muster verwendet, da dies beim Schließen von Dateien (z. B. im Fehlerfall) zuverlässiger ist.
Dies scheint bei mir mit Python 3.6.3 zu funktionieren (erfolgreiches Zusammenführen von 2 partiellen Torrent-Dateien), wurde aber nicht gründlich getestet.
Vielleicht if ...: break
könnte man das Muster entfernen und stattdessen verwendenwhile in1 or in2:
Antwort3
Dies ist kein bitweises Oder, funktioniert aber für (ganze Blöcke von) Nullen:
dd conv=sparse,notrunc if=foo of=baz
dd conv=sparse,notrunc if=bar of=baz
Dadurch sparse
wird das Schreiben von allem, was in der Quelldatei Null ist, übersprungen.
Daher sieht baz wie bar plus alles aus, was in bar Null war, aber nicht Null in foo.
Mit anderen Worten: Wenn es Daten ungleich Null gibt, die in foo und bar nicht identisch sind, gewinnt bar.