Linux provides great tools for doing this albeit not in a very user friendly way. As usually it is best to backup before trying this and make sure the space used fits onto the new drive.
This method can also be used for a bigger drive
Check the drive space used will fit into the smaller drive. Use GParted to get a better visual representation. Otherwise use the command df -h
Create an image using the command below:
sudo dd if=[drive] of=[image file name] bs=512 count=[size to create an image from]
To calculate the size required to 2097152 x [GB] where [GB] is the number of Gigabytes to copy. For example 2097152 x 4
Example command:
sudo dd if=/dev/sdb of=image.bin bs=512 count=8388608
To see the progress of the dd command, another terminal is needed to run this:
watch -n 10 sudo killall -SIGUSR1 dd
Where 10 is how often it will display the progress in seconds. Any updates will appear int he original terminal.
Restoring is a smaller command because it’s reading in the file and needs the drive it’s restoring to and the image:
sudo dd if=image.bin of=/dev/sdb bs=512
DD is a very powerful command and can be used fairly easily to perform disk functions.
Backup and Restore Raspberry Pi images to smaller SD cards, using a Linux computer