How do I convert a Linux disk image into a sparse file?
I have a bunch of disk images, made with ddrescue, on an EXT partition, and I want to reduce their size without losing data, while still being mountable.
How can I fill the empty space in the image's filesystem with zeros, and then convert the file into a sparse file so this empty space is not actually stored on disk?
For example:
> du -s --si --apparent-size Jimage.image
120G Jimage.image
> du -s --si Jimage.image
121G Jimage.image
This actually only has 50G of real data on it, though, so the second measurement should be much smaller.
This supposedly will fill empty space with zeros:
cat /dev/zero > zero.file
rm zero.file
But if sparse files are handled transparently, it might actually create a sparse file without writing anything to the virtual disk, ironically preventing me from turning the virtual disk image into a sparse file itself. :) Does it?
Note: For some reason, sudo dd if=/dev/zero of=./zero.file
works when cat
does not on a mounted disk image.
Solution 1:
First of all, sparse files are only handled transparently if you seek, not if you write zeroes.
To make it more clear, the example from Wikipedia
dd if=/dev/zero of=sparse-file bs=1k count=0 seek=5120
does not write any zeroes, it will open the output file, seek (jump over) 5MB and then write zero zeroes (i. e. nothing at all). This command (not from Wikipedia)
dd if=/dev/zero of=sparse-file bs=1k count=5120
will write 5MB of zeroes and will not create a sparse file!
As a consequence, a file that is already non-sparse will not magically become sparse later.
Second, to make a file with lots of zeroes sparse, you have to cp it
cp --sparse=always original sparsefile
or you can use tar's or rsync's --sparse option as well.
Solution 2:
Perhaps the easiest way to sparsify a file in place would be to use fallocate
utility as follows:
fallocate -v --dig-holes {file_name}
fallocate(1) is provided by util-linux package on Debian.