├── README.md └── qbittorrent-backup-linux.sh /README.md: -------------------------------------------------------------------------------- 1 | # qbittorrent-backup-linux 2 | 3 | Backup your qBitorrent client and restore anytime. 4 | All settings, statistics and torrent list will be saved. 5 | 6 | First, get the script and make it executable: 7 | 8 | ```bash 9 | wget https://raw.githubusercontent.com/cantalupo555/qbittorrent-backup-linux/master/qbittorrent-backup-linux.sh 10 | chmod +x qbittorrent-backup-linux.sh 11 | ``` 12 | Then run it: 13 | 14 | `sudo ./qbittorrent-backup-linux.sh` 15 | 16 | 17 | ## Screenshot 18 | ![](https://i.imgur.com/TADy3tk.png) 19 | 20 | 21 | ## Video 22 | [![qbittorrent-backup-linux](https://i.imgur.com/9NypMuC.png)](https://www.youtube.com/watch?v=MoweTpbMKNU "qbittorrent-backup-linux") 23 | 24 | 25 | ## Compatibility 26 | 27 | **This script works with qBittorrent installed via package manager, Flatpak or both versions.** 28 | 29 | This table lists the tested Linux distributions and their compatibility: 30 | 31 | | Distribution | Version(s) Tested | x86_64 | aarch64 | 32 | |---------------------|-------------------|--------|--------| 33 | | Ubuntu | 22.04+ | ✅ | ✅ | 34 | | Debian | 11+ | ✅ | ✅ | 35 | | Fedora | 34, 35 | 🛑 | 🛑 | 36 | | Arch Linux | Latest | 🛑 | 🛑 | 37 | | Manjaro | Latest | 🛑 | 🛑 | 38 | | openSUSE Tumbleweed | Latest | 🛑 | 🛑 | 39 | 40 | *Note: The script may work on other distributions with similar package management systems and environments, but compatibility has not been thoroughly verified. If you encounter any issues, please report them [here](https://github.com/cantalupo555/qbittorrent-backup-linux/issues/new).* 41 | 42 | 43 | ## Todo 44 | - [x] **Fix script alignment. Completed in commit: [2b4484f](https://github.com/cantalupo555/qbittorrent-backup-linux/commit/2b4484f9c67c412080c5ced8e78a998689b7d5f1) [da5fd9a](https://github.com/cantalupo555/qbittorrent-backup-linux/commit/da5fd9ab9828fe615abf8b5dcdc2c4e881a3b02b)** ✅ 45 | - [x] **Fix dependencies on different Debian-based distributions. Completed in commit: [cebc5b3](https://github.com/cantalupo555/qbittorrent-backup-linux/commit/cebc5b3ccd077a6f9d1a31018c30a793a932c30b)** ✅ 46 | - [x] **Create a list of Linux distributions that have tested the script. [72b7203](https://github.com/cantalupo555/qbittorrent-backup-linux/commit/72b7203d5f090c07705434c1817d1ef3940186e8)** ✅ 47 | - [x] **Make the script compatible with qBittorrent installed via flatpak.[c7364fe](https://github.com/cantalupo555/qbittorrent-backup-linux/commit/c7364fe4398d20c25c75f03c5ca817d57a95a1a4)** ✅ 48 | - [ ] Make it compatible with non-Debian distributions. 🔄 49 | 50 | 51 | ## Feedback 52 | Any suggestions are welcome: [Click here](https://github.com/cantalupo555/qbittorrent-backup-linux/issues/new) 53 | 54 | ## A problem? 55 | Please fill a report [here](https://github.com/cantalupo555/qbittorrent-backup-linux/issues/new) 56 | -------------------------------------------------------------------------------- /qbittorrent-backup-linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check dependencies and user permissions 4 | if [ $UID -ne 0 ]; then 5 | echo -e "\n\033[1;31mRun failed. Try again using:\033[0m" 6 | echo "sudo ./qbittorrent-backup-linux.sh" 7 | exit 1 8 | elif [ ! -f /usr/bin/zip ]; then 9 | echo -e "\n\033[1;31mPlease install the 'zip' package.\033[0m" 10 | echo "sudo apt install zip" 11 | exit 1 12 | elif [ ! -f /usr/bin/unzip ]; then 13 | echo -e "\n\033[1;31mPlease install the 'unzip' package.\033[0m" 14 | echo "sudo apt install unzip" 15 | exit 1 16 | elif [ ! -f /usr/bin/plocate ]; then 17 | echo -e "\n\033[1;31mPlease install the 'plocate' package.\033[0m" 18 | echo "sudo apt install plocate" 19 | exit 1 20 | elif [ ! -f /usr/bin/qbittorrent ] && ( [ -z "$(which flatpak)" ] || [ -z "$(flatpak list | grep org.qbittorrent.qBittorrent)" ] ); then 21 | # Checks if qBittorrent is installed 22 | echo -e "\n\033[1;31mqBittorrent installation not found.\033[0m" 23 | echo "Please install qBittorrent via package manager or Flatpak." 24 | exit 1 25 | fi 26 | 27 | # Return 28 | o1() { 29 | echo "" 30 | echo "-------------------------------------------------------------------------" 31 | echo "-------------------------------------------------------------------------" 32 | echo "-------------------------------------------------------------------------" 33 | echo "Press ENTER to go back!" 34 | echo "" 35 | read v 36 | } 37 | 38 | detect_qbittorrent_config() { 39 | # Detect qBittorrent configuration directory 40 | echo -e "Please wait.\nDetecting configuration qBittorrent client..." 41 | sleep 2 42 | echo -e "\n\033[1;31mThis may take a few seconds.\033[0m" 43 | # Update the locate database to ensure the latest file locations are known 44 | sudo updatedb 45 | sleep 2 46 | 47 | clear 48 | # Search for the qBittorrent configuration directory using plocate 49 | # Store plocate output in array to handle multiple installations 50 | mapfile -t dirCheck < <(plocate *config/qBittorrent/qBittorrent.conf) 51 | # Check if the configuration directory was found 52 | if [ ${#dirCheck[@]} -eq 0 ]; then 53 | # If not found, display an error message and exit 54 | echo -e "\033[1;31mqBittorrent configuration not found, launch qBittorrent client before running this script.\033[0m\n" 55 | exit 1 56 | else 57 | # Handle multiple installations 58 | if [ ${#dirCheck[@]} -eq 1 ]; then 59 | # If only one installation is found, use its directory and user 60 | dir=$(echo "${dirCheck[0]}" | sed 's|\(/home/[^/]*\)/.*|\1/|') 61 | user=$(echo "$dir" | cut -d'/' -f3) 62 | # Check if the installation is a Flatpak 63 | if echo "${dirCheck[0]}" | grep -q "org.qbittorrent.qBittorrent"; then 64 | is_flatpak=true 65 | dirFlatpak=$(echo "${dirCheck[0]}" | sed 's|\(.*org\.qbittorrent\.qBittorrent\).*|\1/|') 66 | else 67 | is_flatpak=false 68 | fi 69 | else 70 | # Let user choose from multiple qBittorrent installations 71 | echo -e "\033[1;32mFound multiple qBittorrent installations:\033[0m\n" 72 | for i in "${!dirCheck[@]}"; do 73 | if echo "${dirCheck[$i]}" | grep -q "org.qbittorrent.qBittorrent"; then 74 | echo -e "\033[38;5;63m$((i+1)) - [Flatpak]\033[0m ${dirCheck[$i]}" 75 | else 76 | echo -e "\033[1;36m$((i+1)) - [Default]\033[0m ${dirCheck[$i]}" 77 | fi 78 | done 79 | echo -e "\033[1;31m3 - Exit\033[0m" 80 | 81 | # Ask the user to choose an installation 82 | echo -e "\n\033[1;33mWhich installation do you want to use? (Input the number: 1, 2 or 3)\033[0m" 83 | read -r choice 84 | 85 | # Handle the user's choice 86 | if [ "$choice" -eq 3 ]; then 87 | clear 88 | echo "You selected option 3." 89 | echo "Exiting..." 90 | exit 1 91 | elif [ "$choice" -le "${#dirCheck[@]}" ] && [ "$choice" -gt 0 ]; then 92 | selected_config="${dirCheck[$((choice-1))]}" 93 | # Use its directory and user based on the choice 94 | dir=$(echo "$selected_config" | sed 's|\(/home/[^/]*\)/.*|\1/|') 95 | user=$(echo "$dir" | cut -d'/' -f3) 96 | # Check if the installation is a Flatpak 97 | if echo "$selected_config" | grep -q "org.qbittorrent.qBittorrent"; then 98 | is_flatpak=true 99 | dirFlatpak=$(echo "$selected_config" | sed 's|\(.*org\.qbittorrent\.qBittorrent\).*|\1/|') 100 | else 101 | is_flatpak=false 102 | fi 103 | else 104 | clear 105 | echo "Invalid choice." 106 | echo "You need to choose between 1 and 3." 107 | echo "Exiting..." 108 | exit 1 109 | fi 110 | fi 111 | fi 112 | } 113 | 114 | # Switch case 115 | while true 116 | do 117 | clear 118 | echo "_________________________________________________________________________" 119 | echo "| |" 120 | echo "| 1 - Backup qBittorrent |" 121 | echo "| 2 - Restore qBittorrent |" 122 | echo "| 3 - Exit |" 123 | echo "|_______________________________________________________________________|" 124 | echo "" 125 | echo "Please select your option 1 to 3:" 126 | read op 127 | 128 | case $op in 129 | 1) while true; do 130 | clear 131 | 132 | # Call the function to detect the qBittorrent configuration directory and user 133 | detect_qbittorrent_config 134 | 135 | # View configuration details 136 | clear 137 | echo "Selected directory: $dir" 138 | echo "Selected user: $user" 139 | if [ "$is_flatpak" = true ]; then 140 | # If it's a Flatpak installation, display the corresponding directory 141 | echo -e "Flatpak directory: ${dirFlatpak}\n" 142 | fi 143 | sleep 3 144 | 145 | # Display a message during backup initialization 146 | cont=1 147 | while [ $cont -ne 4 ]; do 148 | echo -e "\033[1;33mStarting backup...\033[0m\n" 149 | sleep 1 150 | ((cont=$cont+1)) 151 | done 152 | sleep 3 153 | 154 | # Stop the qBittorrent client to prevent conflicts during backup 155 | killall qbittorrent 156 | clear 157 | cont=1 158 | while [ $cont -ne 11 ]; do 159 | echo -e "\033[1;33m.-.-.-.-.-.-.-.-.-.\033[0m\n" 160 | sleep 1 161 | ((cont=$cont+1)) 162 | done 163 | sleep 5 164 | 165 | # Create directory structure for backup 166 | cd $dir 167 | rm -f ${dir}qBittorrent-Backup-Linux.zip 168 | rm -rf ${dir}qBittorrent-Backup-Linux/ 169 | mkdir qBittorrent-Backup-Linux/ 170 | mkdir qBittorrent-Backup-Linux/qBittorrent/ 171 | mkdir qBittorrent-Backup-Linux/BT_backup/ 172 | mkdir qBittorrent-Backup-Linux/logs/ 173 | 174 | # Save configuration data to backup 175 | # Directory change after version 4.2.5 176 | # "LINUX: Don't create 'data' subdirectory in XDG_DATA_HOME (lbilli)" 177 | # https://www.qbittorrent.org/news.php 178 | if [ "$is_flatpak" = true ]; then 179 | cp -R ${dirFlatpak}config/qBittorrent/* qBittorrent-Backup-Linux/qBittorrent/ 180 | cp -R ${dirFlatpak}data/qBittorrent/BT_backup/* qBittorrent-Backup-Linux/BT_backup/ 181 | cp -R ${dirFlatpak}data/qBittorrent/logs/* qBittorrent-Backup-Linux/logs/ 182 | else 183 | cp -R ${dir}.config/qBittorrent/* qBittorrent-Backup-Linux/qBittorrent/ 184 | if [ -d ${dir}.local/share/qBittorrent/ ]; then 185 | cp -R ${dir}.local/share/qBittorrent/BT_backup/* qBittorrent-Backup-Linux/BT_backup/ 186 | cp -R ${dir}.local/share/qBittorrent/logs/* qBittorrent-Backup-Linux/logs/ 187 | else 188 | cp -R ${dir}.local/share/data/qBittorrent/BT_backup/* qBittorrent-Backup-Linux/BT_backup/ 189 | cp -R ${dir}.local/share/data/qBittorrent/logs/* qBittorrent-Backup-Linux/logs/ 190 | fi 191 | fi 192 | 193 | # Checks if the configuration file was copied correctly to the backup 194 | if [ ! -f "$dir"qBittorrent-Backup-Linux/qBittorrent/qBittorrent.conf ]; then 195 | clear 196 | echo -e "\033[1;31mFailed to backup.\033[0m\n" 197 | rm -rf "$dir"qBittorrent-Backup-Linux/ 198 | exit 1 199 | fi 200 | zip -r -0 qBittorrent-Backup-Linux.zip qBittorrent-Backup-Linux/ 201 | rm -rf "$dir"qBittorrent-Backup-Linux/ 202 | 203 | # Set permissions for the backup file 204 | chown $user:$user qBittorrent-Backup-Linux.zip 205 | sleep 2 206 | 207 | # Displays the backup completion message and restore instructions 208 | clear 209 | echo -e "\n\033[1;32mBackup completed.\033[0m\n" 210 | echo "Backup saved to:" 211 | echo -e "\e[1m$dir\e[0m""\e[1mqBittorrent-Backup-Linux.zip\e[0m" 212 | echo -e "\n\n\e[4mHow restore? Have this file anywhere on your system and select option 2.\e[0m" 213 | echo -e "\e[4mAll settings, statistics and torrent list will be restored.\e[0m" 214 | o1 215 | if [ -z "$v" ]; then 216 | break 217 | fi 218 | done 219 | ;; 220 | 221 | 2) while true; do 222 | clear 223 | 224 | # Call the function to detect the qBittorrent configuration directory and user 225 | detect_qbittorrent_config 226 | 227 | # View configuration details 228 | clear 229 | echo "Selected directory: $dir" 230 | echo "Selected user: $user" 231 | if [ "$is_flatpak" = true ]; then 232 | # If it's a Flatpak installation, display the corresponding directory 233 | echo -e "Flatpak directory: ${dirFlatpak}\n" 234 | fi 235 | sleep 3 236 | 237 | # Display a message during restore initialization 238 | cont=1 239 | while [ $cont -ne 4 ]; do 240 | echo -e "\033[1;33mStarting restore...\033[0m\n" 241 | sleep 1 242 | ((cont=$cont+1)) 243 | done 244 | sleep 3 245 | 246 | # Search for the qBittorrent-Backup-Linux.zip file 247 | # Remove any existing backup file in the Trash directory 248 | rm -f $dir.local/share/Trash/files/qBittorrent-Backup-Linux.zip 249 | rm -f $dir.local/share/Trash/info/qBittorrent-Backup-Linux.zip.trashinfo 250 | # Update the locate database to ensure the latest file locations are known 251 | sudo updatedb 252 | bkp=$(plocate qBittorrent-Backup-Linux.zip) 253 | plocate qBittorrent-Backup-Linux.zip > zipCheck 254 | # Count the number of lines in the zipCheck file to determine if there are multiple backup files 255 | zipFile=$(awk 'END{print NR}' zipCheck) 256 | if [ $zipFile -gt 1 ]; then 257 | clear 258 | echo -e "\033[1;31mDuplicate backup file.\033[0m" 259 | echo -e "\033[1;31mKeep only 1 backup file in system.\033[0m\n" 260 | cat zipCheck 261 | rm zipCheck 262 | exit 1 263 | elif [ -z $bkp ]; then 264 | clear 265 | echo -e "\033[1;31mqBittorrent-Backup-Linux.zip file not found.\033[0m\n" 266 | rm zipCheck 267 | exit 1 268 | fi 269 | rm zipCheck 270 | 271 | # Stop the qBittorrent client to prevent conflicts during restore 272 | killall qbittorrent 273 | clear 274 | cont=1 275 | while [ $cont -ne 11 ]; do 276 | echo -e "\033[1;33m.-.-.-.-.-.-.-.-.-.\033[0m\n" 277 | sleep 1 278 | ((cont=$cont+1)) 279 | done 280 | sleep 5 281 | 282 | # Unzip file 283 | cd $dir 284 | rm -rf "$dir"qBittorrent-Backup-Linux/ 285 | unzip $bkp 286 | chown -R $user:$user qBittorrent-Backup-Linux/ 287 | 288 | # Check if the backup file was extracted correctly 289 | if [ ! -f "$dir"qBittorrent-Backup-Linux/qBittorrent/qBittorrent.conf ]; then 290 | clear 291 | echo -e "\033[1;31mFailed to restore.\033[0m\n" 292 | rm -rf "$dir"qBittorrent-Backup-Linux/ 293 | exit 1 294 | fi 295 | 296 | # Restore qBittorrent configuration and data 297 | # Directory change after version 4.2.5 298 | # "LINUX: Don't create 'data' subdirectory in XDG_DATA_HOME (lbilli)" 299 | # https://www.qbittorrent.org/news.php 300 | if [ "$is_flatpak" = true ]; then 301 | rm -rf ${dirFlatpak}config/qBittorrent/* 302 | cp -R qBittorrent-Backup-Linux/qBittorrent/* ${dirFlatpak}config/qBittorrent/ 303 | chown -R $user:$user ${dirFlatpak}config/qBittorrent/ 304 | rm -rf ${dirFlatpak}data/qBittorrent/BT_backup/* 305 | cp -R qBittorrent-Backup-Linux/BT_backup/* ${dirFlatpak}data/qBittorrent/BT_backup/ 306 | chown -R $user:$user ${dirFlatpak}data/qBittorrent/BT_backup/ 307 | rm -rf ${dirFlatpak}data/qBittorrent/logs/* 308 | cp -R qBittorrent-Backup-Linux/logs/* ${dirFlatpak}data/qBittorrent/logs/ 309 | chown -R $user:$user ${dirFlatpak}data/qBittorrent/logs/ 310 | else 311 | rm -rf ${dir}.config/qBittorrent/* 312 | cp -R qBittorrent-Backup-Linux/qBittorrent/* ${dir}.config/qBittorrent/ 313 | chown -R $user:$user ${dir}.config/qBittorrent/ 314 | if [ -d ${dir}.local/share/qBittorrent/ ]; then 315 | rm -rf ${dir}.local/share/qBittorrent/BT_backup/* 316 | cp -R qBittorrent-Backup-Linux/BT_backup/* ${dir}.local/share/qBittorrent/BT_backup/ 317 | chown -R $user:$user ${dir}.local/share/qBittorrent/BT_backup/ 318 | rm -rf ${dir}.local/share/qBittorrent/logs/* 319 | cp -R qBittorrent-Backup-Linux/logs/* ${dir}.local/share/qBittorrent/logs/ 320 | chown -R $user:$user ${dir}.local/share/qBittorrent/logs/ 321 | else 322 | rm -rf ${dir}.local/share/data/qBittorrent/BT_backup/* 323 | cp -R qBittorrent-Backup-Linux/BT_backup/* ${dir}.local/share/data/qBittorrent/BT_backup/ 324 | chown -R $user:$user ${dir}.local/share/data/qBittorrent/BT_backup/ 325 | rm -rf ${dir}.local/share/data/qBittorrent/logs/* 326 | cp -R qBittorrent-Backup-Linux/logs/* ${dir}.local/share/data/qBittorrent/logs/ 327 | chown -R $user:$user ${dir}.local/share/data/qBittorrent/logs/ 328 | fi 329 | fi 330 | 331 | # Clean up the temporary backup directory 332 | rm -rf "$dir"qBittorrent-Backup-Linux/ 333 | sleep 2 334 | 335 | # Displays the restore completion message 336 | clear 337 | echo -e "\n\033[1;32mRestoration completed.\033[0m" 338 | o1 339 | if [ -z "$v" ]; then 340 | break 341 | fi 342 | done 343 | ;; 344 | 345 | 3) 346 | clear 347 | echo "-------------------------------------------------------------------------" 348 | echo "-------------------------------------------------------------------------" 349 | echo "-------------------------------------------------------------------------" 350 | echo "Exit..." 351 | exit 352 | sleep 353 | clear 354 | break 355 | ;; 356 | 357 | *) 358 | clear 359 | echo "-------------------------------------------------------------------------" 360 | echo "-------------------------------------------------------------------------" 361 | echo "-------------------------------------------------------------------------" 362 | echo "Invalid Option!" 363 | sleep 1 364 | echo "" 365 | ;; 366 | esac 367 | done 368 | --------------------------------------------------------------------------------