The two scripts below are for restoring a backup archive of a linux system or user home using fsarchiver.
The first script (system restore) works at partition level, checks if the partition is mounted, unmounts it and unpacks the archive there.
The 2nd script (user home restore) works at dir level and looks for a dir in /home or another partition, or uses /mnt/tmp. It is advisable to create a new dir there (you can do this during dir selection by typing 'm' and it will ask for new dir name) and not unpack onto your current user home. You could also unpack a user home backup archive into /mnt/tmp and then run rsync to copy files into your running user home.
See my
System backup page for more info.
1. System restore (with fsarchiver)
2. User home restore (with fsarchiver)
#!/bin/bash
# bkprestore-sys-fs
# Quick system restore with fsarchiver, by David Quinton, two days in Dec 2025
# Only operates with archives made with fsarchiver (.fsa extensions).
# Make Linux not war!!
#===================================Variables
Loc=/media/Bkp/zsysbkp
ZSTD_NBTHREADS=0
#===================================Functions
chooseFile () {
cd $Loc
while true; do
clear
printf '\n%.0s' {1..10}; printf "Choose an archive to restore! (.fsa)
../ to enter parent directory.\n\n"
ls -dhl --color=auto "$(pwd)"
IFS=$'\n' COLUMNS=1 PS3="Enter choice:"
options=(../ $(ls -hl . 2>/dev/null)) # ls -hl /media/Bkp/zsysbkp | grep -e 'xz' -e 'zst' -e 'fsa'
select opt in "${options[@]}"; do
FilePath=$(pwd)/$(echo "$opt" | awk '{print $9}')
case $opt in
../) cd .. && break ;;
*) if [[ -f "$FilePath" ]]; then #check if $FilePath is a file, then File=FilePath
File=$FilePath; break 3
elif [[ "$opt" ]]; then
dirname=$(echo "$opt" | awk '{print $9}')
cd "$dirname"; break #if $opt is a dir then cd
else break; fi ;;
esac
done
done
# determine ext of $File, 1st strip path from $File, then grep ext and test success or not
file=`basename $File`
if [[ `echo $file | grep '\.fsa'` ]]; then break #check if file contains string .fsa
else printf "Your file does not carry an .fsa extension! Aborting now!"; exit 0
fi
}
#select partition
choosePart () {
while true; do
clear; lsblk
printf '\n%.0s' {1..5}; printf "\tSelect a partition - Warning it will be overwritten!\n\n"
PS3="Select (type C to cancel): "
options=($(ls /sys/class/block | grep -E '^(sd|hd|vd|nvme)[a-z][0-9]+|[0-9]p[0-9]+'))
select opt in "${options[@]}"; do
if [[ "$REPLY" == [cC] ]]; then
echo "Aborted!" && return 1
elif [[ -n "$opt" ]]; then Part=/dev/$opt; return 0
else printf "Invalid option"
fi
done
done
}
formatPart () {
#check if part is mounted, find its mount point and mount at /mnt if not
if findmnt $Part > /dev/null; then
mounted=$(findmnt -n -o TARGET $Part); printf "Unmounting the partition $Part"; sudo umount $mounted
else printf "\n\n\tGood news, $Part is not mounted! Continuing..."
fi
}
#===================================Unpack commands
unpackFile () {
sudo fsarchiver restfs -vo -j 14 $File id=0,dest=/dev/$opt,mkfs=ext4
sudo mount /dev/$opt /mnt/$opt && printf "\n\n\t/dev/$opt mounted to /mnt/$opt\n\n"
}
taskConfirm () {
while true; do
clear
printf '\n%.0s' {1..4}; printf "\tTask set.....\n\n
Archive: $File \n\n\tTarget: /dev/$opt\n\n
Hit Enter to proceed! Or type C and Enter to abort!\n"
read ans
case $ans in
"") unpackFile; break 2 ;;
[cC]*) exit 0 ;;
*) break ;;
esac
done
}
#===================================Start
chooseFile
choosePart
formatPart
taskConfirm