Skip to main content

qBt Migrate

Python QA Checks

This tool changes the paths of existing torrents in qBittorrent in a bulk fashion. It can also convert slashes when migrating between Windows and Linux/Mac.

Demo

Also check out my Chrome Extension for handling TV Episode torrents.

qBt TV Torrent Upload

Chrome Web Store

Source

Usage

qBittorrent must be closed before qbt_migrate writes anything. It keeps resume data in memory and writes .fastresume files back out when it exits, so editing them underneath a running client just gets your changes overwritten.

qbt_migrate checks for this and refuses to write while it finds qBittorrent running. Interactively it offers to stop it for you; pass -k / --stop-qbittorrent to skip the question. Either way it sends a normal quit (never a force kill, which would skip the resume data flush) and waits for the process to actually disappear before touching anything. --ignore-running overrides the check if you know better.

--dry-run is exempt, since it writes nothing.

NOTE: detection is best effort. Inside a container /proc only shows the container's own processes, so a qBittorrent running on the host is invisible to it. Close it yourself when running via Docker.

Install from PyPi using pip, or run with Docker.

pip install qbt_migrate

Run the script and follow prompts or use CLI arguments with command qbt_migrate

usage: qbt_migrate [-h] [-e EXISTING_PATH] [-n NEW_PATH] [-r] [-t {Windows,Linux,Mac}] [-b BT_BACKUP_PATH] [-s] [-k] [--ignore-running] [-d] [-z]
                   [-l {DEBUG,INFO}] [-v]

options:
  -h, --help            show this help message and exit
  -e EXISTING_PATH, --existing-path EXISTING_PATH
                        Existing root of path to look for.
  -n NEW_PATH, --new-path NEW_PATH
                        New root path to replace existing root path with.
  -r, --regex           Existing and New paths are regex patterns. (Capture groups recommended).
  -t {Windows,Linux,Mac}, --target-os {Windows,Linux,Mac}
                        Target OS (converts slashes). Default will auto-detect if conversion is needed based on existing vs new.
  -b BT_BACKUP_PATH, --bt-backup-path BT_BACKUP_PATH
                        BT_backup Path Override.
  -s, --skip-bad-files  Skips bad .fastresume files instead of exiting. Default behavior is to exit.
  -k, --stop-qbittorrent
                        Stop a running qBittorrent without asking first, and wait for it to exit.
  --ignore-running      Run even if qBittorrent is still running. Unsafe: it will overwrite your changes from memory when it exits.
  -d, --dry-run         Show what would change and exit without writing anything.
  -z, --skip-backup     Skips creating a backup zip archive of the BT_backup folder. Default behavior is to create a backup.
  -l {DEBUG,INFO}, --log-level {DEBUG,INFO}
                        Log Level, Default is INFO.
  -v, --version         Prints the current version number and exits.

Check before you commit to it

Pass -d / --dry-run to see exactly what would change, per file and per key, without writing anything. Trailing separators are the most common way to get this wrong, so values are quoted to make them visible.

$ qbt_migrate -e 'S:\' -n /mnt/s/ --dry-run
Auto detected target OS change. Will convert slashes to Linux/Mac.
🔍 Dry run. Searching for .fastresume files with path S:\ ...
Ubuntu 24.04.1 LTS Desktop (amd64)
    save_path         'S:\Pictures\' -> '/mnt/s/Pictures/'
    qBt-savePath      'S:\Pictures\' -> '/mnt/s/Pictures/'
    qBt-downloadPath  'S:\Incomplete\' -> '/mnt/s/Incomplete/'
    mapped_files      2 of 2 entries, e.g. 'S:\Pictures\a.jpg' -> '/mnt/s/Pictures/a.jpg'
🔍 1 of 1 relevant fastresume file would be updated. Nothing was written.

Torrents are identified by name rather than by the info hash their .fastresume is named after. The name comes from qBt-name, then libtorrent's name, then the sibling <hash>.torrent, falling back to the hash when none of those exist (a magnet with no metadata yet).

Large libraries list the first 20 files and a count of the rest. Add -l DEBUG to see all of them.

Anything not passed as an argument is prompted for. When nothing is attached to stdin (a container without -it, cron, a shell script), qbt_migrate does not prompt: it uses the defaults it can (platform BT_backup path, no regex, target OS auto-detected) and exits with a message naming the argument if -e or -n is missing.

Exit codes: 0 success, 1 one or more .fastresume files could not be read or updated, 2 bad or missing arguments.

By default, everything happens in the BT_backup directory defined by the OS the script is running on. Override BT_backup path if needed.

Default BT_backup paths, checked in this order and matching how qBittorrent itself resolves them:

  • Windows: %LOCALAPPDATA%\qBittorrent\BT_backup
  • Mac: $HOME/Library/Application Support/qBittorrent/BT_backup
  • Linux: $XDG_DATA_HOME/qBittorrent/BT_backup ($HOME/.local/share when unset), falling back to the pre-4.x $XDG_DATA_HOME/data/qBittorrent/BT_backup when only that one exists
  • Docker: /config/qBittorrent/BT_backup, checked first when running in a container

Run with -l DEBUG to see which candidates were checked and which one was picked.

A backup zip archive is automatically created in the BT_backup directory. Pass -z / --skip-backup to skip it, which is worth doing when you already have one and are making a series of path changes over a large library, since zipping every run gets slow.

Examples

Assuming all of our torrents are in X:\Torrents when coming from Windows, or /torrents when coming from Linux/Mac

NOTE: When running qbt_migrate on a Linux/Mac machine, Windows paths will require double \. Ex. C:\\Users\\user\\Downloads\\Torrents

NOTE: Take note of trailing slash replacement when changing from Windows <-> Linux. -e X:\ -n /torrents will result in /torrentsxxxxx, not /torrents/xxxxx. The correct pattern for this would be -e X: -n /torrents or -e X:\ -n /torrents/.

docs/paths.md covers escaping, separators, and trailing slashes in full. If paths are not being replaced the way you expect, read that first.

qbt_migrate -e X:\ -n Z:\ -t Windows  # Windows to Windows (Drive letter change)
qbt_migrate -e X:\Torrents -n X:\NewDir\Torrents -t Windows  # Windows to Windows (Directory Change)
qbt_migrate -e X:\Torrents -n Z:\NewDir\Torrents -t Windows  # Windows to Windows (Drive letter change with directory change)
qbt_migrate -e X: -n /torrents -t Linux  # Windows to Linux/Mac (converts slashes)  # When running on Linux machine \\ is needed for Windows Paths  # Note Trailing Slash
qbt_migrate -e X:\Torrents -n /torrents -t Linux  # Windows to Linux/Mac (converts slashes)  # When running on Linux machine \\ is needed for Windows Paths
qbt_migrate -e X:\\Torrents -n /torrents -t Linux  # Windows to Linux/Mac (converts slashes)  # When running on Linux machine \\ is needed for Windows Paths

qbt_migrate -e /torrents -n /new/path/for/torrents  # Changes torrent root path on Linux/Mac
qbt_migrate -e /torrents -n Z:\Torrents -t Windows  # Linux/Mac to Windows (converts slashes)
qbt_migrate -e /torrents -n Z:\\Torrents -t Windows  # Linux/Mac to Windows (converts slashes)  # When running on Linux machine \\ is needed for Windows Paths

# Adavanced Usage with RegEx
# Example would replace /some/test/with/a/path with /test/matched/path
qbt_migrate -r -e /some/(\w+)/.*$ -n \1/matched/path -t Linux  # Matches using regex patterns and replaces using capture groups.
qbt_migrate --regex -e /some/(\w+)/.*$ -n \1/matched/path -t Linux  # Matches using regex patterns and replaces using capture groups.

Docker

You can also run this tool with Docker if you don't have Python, or don't want to install the package to your system directly. The BT_backup path is automatically overridden to /tmp/BT_backup, so mount your BT_backup there.

Images are published for linux/amd64 and linux/arm64 to both registries:

  • jslay88/qbt_migrate (Docker Hub)
  • ghcr.io/jslay88/qbt_migrate (GitHub Container Registry)

Tags: latest and X.Y.Z track releases, master tracks the default branch.

NOTE: When running qbt_migrate Docker image on a Linux/Mac machine, Windows paths will require double \. Ex. C:\\Users\\user\\Downloads\\Torrents

The Docker image has all functionality as the pip install, following the same arguments/patterns listed in the above examples.

Add -it if you want to be prompted for anything you leave off. Without it, arguments you omit fall back to their defaults instead of prompting.

For example, mounting in the default BT_backup path on a Windows machine running Docker

docker run --rm -v %LOCALAPPDATA%/qBittorrent/BT_backup:/tmp/BT_backup jslay88/qbt_migrate -e X:\ -n Z:\  # Windows to Windows (Drive letter change)
docker run --rm -v %LOCALAPPDATA%/qBittorrent/BT_backup:/tmp/BT_backup jslay88/qbt_migrate -e X:\Torrents -n X:\NewDir\Torrents -t Windows  # Windows to Windows (Directory Change)
...

Mounting in the default BT_backup path on a Linux/Mac machine running Docker

docker run --rm -v $HOME/.local/share/qBittorrent/BT_backup:/tmp/BT_backup jslay88/qbt_migrate -e X:\ -n Z:\  # Windows to Windows (Drive letter change)
docker run --rm -v $HOME/.local/share/qBittorrent/BT_backup:/tmp/BT_backup jslay88/qbt_migrate -e X:\Torrents -n X:\NewDir\Torrents -t Windows  # Windows to Windows (Directory Change)
...

If for some reason you wanted to override BT_backup path from /tmp/BT_backup within the container, simply set environment variable BT_BACKUP_PATH on the container to where you will be mounting in.

The -e for environment variable override must go before the image jslay88/qbt_migrate as the -e after the image is for --existing-path

docker run --rm -v %LOCALAPPDATA%/qBittorrent/BT_backup:/opt/qbt_migrate/fastresume -e BT_BACKUP_PATH=/opt/qbt_migrate/fastresume jslay88/qbt_migrate -e X:\ -n Z:\  # Windows to Windows (Drive letter change)
...

You can also clone this repository, build the image, and run your own built image

docker build . -t qbt_migrate
docker run --rm -v %LOCALAPPDATA%/qBittorrent/BT_backup:/tmp/BT_backup qbt_migrate -e X:\ -n Z:\  # Windows to Windows (Drive letter change)
...

Contributing

See CONTRIBUTING.md. tox -e lint and tox -e unittest are what CI runs.

Python Module

This project has also been built to be modular and used as a Python Module. If you feel like utilizing this project within your own, please feel free to do so, and let me know!

Use Cases:

  • UI for qbt_migrate
  • FastResume Class
  • Torrent Manager

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qbt_migrate-3.3.0.tar.gz (24.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qbt_migrate-3.3.0-py3-none-any.whl (24.9 kB view details)

Uploaded Python 3

File details

Details for the file qbt_migrate-3.3.0.tar.gz.

File metadata

  • Download URL: qbt_migrate-3.3.0.tar.gz
  • Upload date:
  • Size: 24.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for qbt_migrate-3.3.0.tar.gz
Algorithm Hash digest
SHA256 17c158c2c7080386e93c66e2770f2567d1c854b7054d62039137cef8331f7b3a
MD5 3048f9263e8e5c51ea70329bf162c0c5
BLAKE2b-256 0f8838db4493e3a7b70ff36bb53072d8145f548bfcd88beded9dfb0366ed73ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for qbt_migrate-3.3.0.tar.gz:

Publisher: release.yml on jslay88/qbt_migrate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file qbt_migrate-3.3.0-py3-none-any.whl.

File metadata

  • Download URL: qbt_migrate-3.3.0-py3-none-any.whl
  • Upload date:
  • Size: 24.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for qbt_migrate-3.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9c7eb6f5f33214fb6d451b3b662ba6c459df30ad19e3ea75ae1441bc200de613
MD5 506911f9bf0bfaccd6ee74bdb6cae002
BLAKE2b-256 f586f0b3a43064632f25e54c319556dfb3d9c2a0507f4a58bae74157b827e522

See more details on using hashes here.

Provenance

The following attestation bundles were made for qbt_migrate-3.3.0-py3-none-any.whl:

Publisher: release.yml on jslay88/qbt_migrate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

3.3.0 This release

2 files

3.2.0

2 files

3.1.0

2 files

3.0.0

2 files

2.3.2

2 files

2.3.1

2 files

2.3.0

2 files

2.2.1

2 files

2.2.0

2 files

2.1.6

2 files

2.1.5

2 files

2.1.4

2 files

2.1.3

2 files

2.1.2

2 files

2.1.0

2 files

2.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page