One low-tech and fast possibility is to shrink the filesystem(s) to little more than what they contain, reproduce the partition table, and reproduce only the occupied part of each partition. After the copy, enlarge each filesystem to fill its partition.
But you should use tools that solve this problem for you. Partimage can save and restore a filesystem and only saves the used part. So can Clonezilla. So really the answer to your question is: use partimage or clonezilla.
Beware that when you do such deployment, you'll end up with identical filesystems on all machines. You'll have the same UUIDs for the filesystems, the same initial RNG state, the same private SSH key, etc. The UUID collisions don't matter as long as each clone evolves independently, but this violates the expectation that UUIDs are unique, and can be a problem e.g. if filesystem from multiple clones end mounted up on the same machine. The RNG state can be problematic if the instances are started up and used before they have time to be collected on their own. The private keys are definitely a problem. So after cloning, you should do a step of personalization on each instance (see also Moving linux install to a new computer).
An alternative approach is to create a new filesystem on each clone and copy the files individually (with cp -a
— in my experience, GNU cp
is good at preserving all metadata). However this is likely to be slower than a straight filesystem copy, especially on rotating media (HDD as opposed to flash) where reading the files will involve a lot of seeking back and forth.