How to Create a USB Drive Image Without Unallocated Space Using dd and Partclone


3 views

When working with USB drives in Linux, you'll often encounter situations where not all disk space is allocated to partitions. The fdisk -l output shows a typical case:

Disk /dev/sdb: 8462 MB, 8462008320 bytes
255 heads, 63 sectors/track, 1028 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes

Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1           9       72261    e  W95 FAT16 (LBA)
/dev/sdb2              10         103      755055   83  Linux

The conventional dd approach captures all sectors, including unallocated space:

dd if=/dev/sdb of=myimage.img bs=1M

This creates an 8GB file when we only need about 1GB for the actual partitions.

Here are three practical methods to create space-efficient images:

Method 1: Partition-Level Imaging

Create separate images for each partition:

dd if=/dev/sdb1 of=fat_partition.img bs=1M
dd if=/dev/sdb2 of=linux_partition.img bs=1M

Method 2: Using partclone

The partclone tool is specifically designed for this purpose:

partclone.ext2 -c -s /dev/sdb2 -o linux_partition.pcl
partclone.fat -c -s /dev/sdb1 -o fat_partition.pcl

Method 3: Combined Approach with sfdisk

First backup the partition table:

sfdisk -d /dev/sdb > partitions.sfdisk

Then create compressed images of each partition:

partclone.ext2 -c -s /dev/sdb2 | gzip > linux_partition.img.gz
partclone.fat -c -s /dev/sdb1 | gzip > fat_partition.img.gz

To restore to a new USB drive:

sfdisk /dev/sdX < partitions.sfdisk
partclone.ext2 -r -s linux_partition.pcl -o /dev/sdX2
partclone.fat -r -s fat_partition.pcl -o /dev/sdX1

For even more space savings, consider sparse files:

dd if=/dev/sdb of=sparse.img bs=1M conv=sparse

This creates a file that only stores non-zero blocks, appearing as 8GB but consuming less actual disk space.

While partclone is generally faster for partition imaging, dd offers more control over block sizes. For best results with partclone:

partclone.ext2 -c -s /dev/sdb2 -o linux_partition.pcl -b -q

The -b enables buffering and -q reduces output verbosity.


When working with USB drives containing unallocated space, the standard dd approach creates unnecessarily large image files. Consider this common scenario:

[root@host]# fdisk -l /dev/sdb
Disk /dev/sdb: 8462 MB, 8462008320 bytes
255 heads, 63 sectors/track, 1028 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
/dev/sdb1   *           1           9       72261    e  W95 FAT16 (LBA)
/dev/sdb2              10         103      755055   83  Linux

Running dd if=/dev/sdb of=myimage.img bs=1M would produce an 8GB file, while only about 1GB contains actual data.

The most straightforward solution is to image only the allocated partitions:

# Image the FAT partition
dd if=/dev/sdb1 of=fat_partition.img bs=1M

# Image the Linux partition  
dd if=/dev/sdb2 of=linux_partition.img bs=1M

This creates separate image files totaling approximately 827MB (72MB + 755MB).

For tools requiring a single image file, we can use these approaches:

Method 1: Using sfdisk and dd

# Save partition table
sfdisk -d /dev/sdb > partitions.sfdisk

# Calculate total used blocks
END_SECTOR=$(sfdisk -l -o End /dev/sdb | tail -1)
BLOCK_SIZE=512
IMAGE_SIZE=$(( (END_SECTOR + 1) * BLOCK_SIZE ))

# Create optimized image
dd if=/dev/sdb of=optimized.img bs=1M count=$((IMAGE_SIZE/1048576 + 1))

Method 2: Using parted for Precision

# Get last sector of last partition
LAST_SECTOR=$(parted /dev/sdb unit s print | grep -A2 "Number" | tail -1 | awk '{print $3}' | tr -d 's')

# Calculate image size
dd if=/dev/sdb of=compact.img bs=512 count=$((LAST_SECTOR + 1))

For even better space management:

dd if=/dev/sdb of=sparse.img bs=1M conv=sparse

This creates a sparse file that only occupies actual data blocks on disk while appearing as a full-size image to applications.

When working with emulators like QEMU:

# Create qcow2 image (dynamically allocated)
qemu-img convert -f raw -O qcow2 optimized.img bootable.qcow2

This creates a compressed, efficient image file that only grows as data is written.

Always verify your images:

# Check file sizes
ls -lh *.img

# Verify partition structure
fdisk -l optimized.img

# Test bootability
qemu-system-x86_64 -hda optimized.img