Imagine that I have a disk that is 128GB in size. On this disk, only 12GB is used. 116GB of the disk is empty space containing all zeroes (0x00).

I want to take an exact snapshot of the disk such that it can be exactly reconstructed in its current state in the future. To save space in the compressed image I'll pass it through a fast compression algorithm like lz4 or zstd.

I can do this with dd, pv or similar tools, like this:

pv /dev/sdb | lz4 > disk.image.lz4

Now I have a disk image file that is around, say, 10GB in size, but actually contains a full 128GB image complete with zeros - the zeros were just compressed out.

Now later I want to write this image back to the disk. Naturally I can do this:

lz4 -d -c disk.image.lz4 > /dev/sdb

However the problem here is that writing the image back to disk can take a long time, since it is writing everything back to the disk - even the zeros.

Suppose one of two things: either that I don't care whether the blocks that used to be zeros still are zeros on the copy, or if it is an SSD I might just use blkdiscard to discard all blocks on the SSD prior to writing the image, in effect zeroing out the disk in a matter of seconds.

Question: Is there a tool that can read the source image block-by-block, detect zeros, and simply skip writing those blocks on the output device?

For example, if we were working with 1MB blocks, my ideal tool would read 1MB of data, check to see if it is all 0x00, and if not, write it to the same position on the destination. If the block is indeed all 0x00, then just skip writing it altogether.

Here's why this would be an advantage:

  • Writing all blocks on the destination disk can take a very long time. Especially if we are working with a spinning hard drive >2TB in size but which only contains a relatively small amount of actual data.
  • It's quite a waste to use up SSD write cycles writing 0x00 to the entire drive when only a relatively small portion of the drive might contain data we care about.
  • Since the image is being decompressed while it is written, this does not impose any extra read I/O to the source device.

I'm thinking of writing a simple tool to accomplish this if it doesn't exist already, but if there is a way to do this already, what is it?

EDIT: To give a little more detail, one example use case for this would be backing up a hard disk partition that contains an activated software license. A simple file copy or even a filesystem-aware partition image is unlikely to restore properly depending on the activation scheme. (For example, if an authorization scheme stores data in unallocated space, in sectors that are deliberately marked bad in the file table even though they're not, within the MFT itself on NTFS, etc). Thus, a bit-for-bit copy of everything that's not all zeros would be necessary to ensure that restoring the partition would still yield a valid license.

  • 1
    Reasonably sure that clonezilla does this; and I have a feeling most imaging software also does this. But really I feel like your problem stems from the fact you aren't actually using an imaging tool, but a compression tool. Since lossless compression (which is what lz4 does) implies that you want to retain all of the data you compressed, the context of the situation (disk to disk imaging) isn't important to the tool(lz4).
    – ReedGhost
    Commented Jul 8, 2021 at 21:04
  • i.e. outputting an entire disk to zip,tar,lz4, etc. isn't an efficient way to make images in the first place, since that is not what the design methodology for that software was made to handle. I do images with Clonezilla of servers with upwards of 20TB of disk space, which take 20 minutes per server on average to apply(since its only roughly 50-100GB of data on the disks), and I have a feeling most other non-forensic imaging software provides similar results.
    – ReedGhost
    Commented Jul 8, 2021 at 21:09

2 Answers 2


With an uncompressed (and probably sparse itself) source file, simply using (GNU) cp --sparse=always sourcefile /dev/sdX would be enough:


control creation of sparse files. See below

By default, sparse SOURCE files are detected by a crude heuristic and the corresponding DEST file is made sparse as well. That is the behavior selected by --sparse=auto. Specify --sparse=always to create a sparse DEST file whenever the SOURCE file contains a long enough sequence of zero bytes. Use --sparse=never to inhibit creation of sparse files.

Creating a sparse file is simply done by seeking instead of writing. On a block device, that's exactly what OP seeks (pun intended).

Likewise lz4 has sparse support:


Sparse mode support (default:enabled on file, disabled on stdout)

lz4 -d -c --sparse disk.image.lz4 > /dev/sdX

This would also work (probably without even having to specify --sparse) but would warn first about overwriting a file:

lz4 -d --sparse /tmp/src.img.lz4 /dev/sdX

And finally for other cases (GNU?) dd itself has sparse support:

sparse try to seek rather than write all-NUL output blocks

lz4 -d -c disk.image.lz4 | dd conv=sparse of=/dev/sdX

(I would probably also set bs= to a size similar to the SSD's erase block size, probably ~ 1M, rather than keep the 512 bytes default).


Yes - have a look at Clonezilla.

It won't copy unused unused portions of your filesystem to the backup image (or unallocated portions of your disk either). However if you have a sparse file which the filesystem sees as one big allocation, then it will be treated as such, regardless of content.

Clonezilla also passes the selected output through a compression program, there are many to choose from, including parallel gzip.

If you have some kind of "raw" disk access, then you read or write what you like, but you will have to invent a method of indicating where the missing zero blocks are. You could just store your file in a compressed way, decompressing 'on the fly'. I believe there was a product for DOS - 20+ years ago that did this; it wasn't very good at coping with errors.

You must log in to answer this question.

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