
Hace un tiempo hice 2 intentos de rescate en un disco duro moribundo; Primero ejecuté (GNU) ddrescue
y luego directamente dd
con la búsqueda manual. Quiero obtener lo mejor de ambas imágenes. Dado que cualquier tramo vacío en los archivos será solo 0, el AND bit a bit debería ser suficiente para fusionar los dos archivos.
¿Existe alguna utilidad que me permita crear un archivo que sea el OR de dos archivos de entrada?
(Estoy usando ArchLinux, pero estoy feliz de instalarlo desde la fuente si no está en los repositorios)
Respuesta1
No conozco ninguna utilidad que haga esto, pero debería ser bastante fácil escribir un programa para hacerlo. Aquí hay un ejemplo esquelético en 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()
O un programa en C que debería ejecutarse más rápido (pero es mucho más probable que tenga un error desapercibido):
#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;
}
}
Respuesta2
Pitón
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)))
Esto es aproximadamente 10 veces más rápido que la solución Python de Chris debido a que lee 1024 bytes a la vez. También utiliza el with open
patrón, ya que es más fiable para cerrar archivos (por ejemplo, en caso de error).
Esto parece funcionar para mí con Python 3.6.3 (fusionando con éxito 2 archivos torrent parciales), pero no se ha probado exhaustivamente.
Quizás el if ...: break
patrón podría eliminarse y en su lugar utilizarwhile in1 or in2:
Respuesta3
Esto no es bit a bit, pero funciona para (bloques enteros de) ceros:
dd conv=sparse,notrunc if=foo of=baz
dd conv=sparse,notrunc if=bar of=baz
Debido a sparse
que omite escribir cualquier cosa que sea cero en el archivo fuente.
Entonces baz se verá como bar, más lo que fuera cero en bar pero no cero en foo.
En otras palabras, si hay datos distintos de cero que no son idénticos en foo y bar, bar gana.