I did 2 rescue attempts on a dying HDD a while back; I ran (GNU) ddrescue first, and then straight dd with manual seeking. I want to get the best of both images. Since any empty stretches in the files will just be 0's, bitwise-AND should be sufficient to merge the two files.

Is there a utility that allows me to create a file that is the OR of two input files?

(I am using ArchLinux, but I'm happy to install from source if it's not in the repos)

  • Wouldn't you want a bitwise-OR if you expect bad parts to be a stretch of zeros?
    – Chris
    Nov 4, 2016 at 19:09
  • oh, right. of course. Editing now...
    – user371366
    Nov 4, 2016 at 19:27
  • It would be interesting to run cmp -l image1 image2 to verify that the only differences are zero-vs-nonzero. Nov 9, 2016 at 12:16

3 Answers 3


I don't know of a utility that does this, but it should be pretty easy to write a program to do this. Here's a skeletal example in python:

#!/usr/bin/env python
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
     elif (data2): #If image2 is longer, clean up
     else: #No cleanup needed if images are same length

Or a C program that should run faster (but is significantly more likely to have an unnoticed bug):

#include <stdio.h>
#include <string.h>

#define BS 1024

int main() {
    FILE *f1,*f2,*fout;
    size_t bs1,bs2;
    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
        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
  • h.write(chr(ord(data1) | ord(data2))) TypeError: a bytes-like object is required, not 'str'
    – Zaz
    Nov 1, 2019 at 20:15
  • 1
    @Zaz The above is python 2 code. Due to changes in str versus bytes introduced in python 3, it needs a little modification to run in python 3. One hacky way to do it would be change chr(ord(data1)|ord(data2)) to bytes([ord(data1)|ord(data2)]).
    – Chris
    Nov 1, 2019 at 21:05


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:
        out.write(bytes(b1 | b2 for (b1, b2) in zip(bytes1, bytes2)))

This is roughly 10× faster than Chris's Python solution due to reading 1024 bytes at a time. It also uses the with open pattern as this is more reliable at closing files (e.g. in case of error).

This seems to work for me with Python 3.6.3 (successfully merging 2 partial torrent files), but has not been thoroughly tested.

Perhaps the if ...: break pattern could be removed and instead use while in1 or in2:

  • Why not convert the bytes to integer and then bitwise-or | the integers converting the result back to bytes to write them out? This would help to avoid an explicit generator loop and avoiding explicit loops is usually a good idea to speed things up.
    – Claudio
    Aug 6, 2023 at 15:29

This is not bitwise or, but it works for (whole blocks of) zeroes:

dd conv=sparse,notrunc if=foo of=baz
dd conv=sparse,notrunc if=bar of=baz

Due to sparse it skips writing anything that is zero in the source file.

So baz will look like bar, plus whatever was zero in bar but not zero in foo.

In other words if there's non-zero data that's not identical in foo and bar, bar wins.

  • Nice. In order to replicate the same results, wouldn't you want bs=1?
    – Chris
    Nov 1, 2019 at 22:29
  • bs=1 would still be byte-wise not bit-wise. and awful performance-wise. The default bs=512 or even bs=4K would be fine for the situation in the OP as dd(rescue) would get whole sectors or nothing. For the Torrent use case (@Zaz answer) I guess it depends if you also want to preserve incomplete-chunks... no idea which resolution those are written at (if at all) Nov 1, 2019 at 22:46
  • Yes, I know it would be byte-wise not bit-wise, but it's impossible for programs to write part of a byte to a file, so that isn't a problem. Of course you're right about performance, but I suspect dd will still beat python at least by miles.
    – Chris
    Nov 1, 2019 at 22:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .