So I had the same issue, here's how I approached it:
0) Re-create all your categories you have on Windows, on the Linux qBittorrent client
1) shutdown qbt on all your machines (both windows and linux)
2) transfer all torrent DATA FILES and KEEP THE SAME FILE STRUCTURE (from windows to linux)
e.g. I had everything in V:\downloads and U:\downloads and transfered everything to /data/torrents/downloads
3) Download Visual Studio Express and create a new C# Console Application (name of the project must be qBTConverter) and paste this source code (I made this, you can also run this with mono on linux, should work):
Code: Select all
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace qBTConverter
{
class Program
{
static bool Match(ref byte[] data, ref byte[] search, int data_index)
{
if(data.Length <= data_index + search.Length)
{
return false;
}
for(int i = 0; i < search.Length; ++i)
{
if(data[data_index + i] != search[i])
{
return false;
}
}
return true;
}
static int Position(ref byte[] data, string find_what, int start_pos = 0)
{
byte[] search = Encoding.UTF8.GetBytes(find_what);
for (int i = start_pos; i < (data.Length - search.Length); ++i)
{
if(Match(ref data, ref search, i))
{
return i;
}
}
return -1;
}
static byte[] Extract(ref byte[] data, int start, int end)
{
int size = end - start;
if(size < 0)
{
return null;
}
byte[] buffer = new byte[size];
for(int i = 0; i < size; ++i)
{
buffer[i] = data[start + i];
}
return buffer;
}
public static byte[] Combine(byte[] first, byte[] second, byte[] third)
{
byte[] ret = new byte[first.Length + second.Length + third.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
Buffer.BlockCopy(third, 0, ret, first.Length + second.Length, third.Length);
return ret;
}
static byte[] ReplaceBytes(ref byte[] data, int from, int to, byte[] with)
{
byte[] first = data.Take(from).ToArray();
byte[] second = data.Skip(to).Take(data.Length - to).ToArray();
return Combine(first, with, second);
}
static bool Replace(ref byte[] data, string which, string location, string replace)
{
int pos_a = Position(ref data, which);
if(pos_a == -1)
{
return false;
}
int pos_b = pos_a + Encoding.UTF8.GetBytes(which).Length;
int pos_c = Position(ref data, ":", pos_b);
byte[] b_len = Extract(ref data, pos_b, pos_c);
int len = Int32.Parse(Encoding.UTF8.GetString(b_len));
byte[] b_path = Extract(ref data, pos_c + 1, pos_c + len + 1);
string path = Encoding.UTF8.GetString(b_path);
if(path.IndexOf(location) == -1)
{
return false;
}
path = path.Replace(location, replace).Replace("\\", "/");
byte[] r_path = Encoding.UTF8.GetBytes(path.Length.ToString() + ":" + path);
data = ReplaceBytes(ref data, pos_b, pos_c + len + 1, r_path);
return true;
}
// :qBt-savePath<len>:<len chars>
// :save_path<len>:<len chars>
static void Main(string[] args)
{
if(args.Length < 3)
{
Console.WriteLine("Usage: qBTConverter <path> <windows base directory> <linux base directory>");
return;
}
if(args[0][args[0].Length-1] == '\\')
{
args[0].Remove(args[0].Length - 1);
}
Console.WriteLine("Using path \"" + args[0] + "\"");
Console.WriteLine("Search \"" + args[1] + "\"");
Console.WriteLine("Replace \"" + args[2] + "\" & \\ -> /");
string[] files =
Directory.GetFiles(args[0], "*.fastresume", SearchOption.TopDirectoryOnly);
if (files.Length < 1)
{
Console.WriteLine("No .fastresume files found in path");
return;
}
Console.WriteLine("Found " + files.Length.ToString() + " fastresume files");
string outpath = args[0] + "\\out";
System.IO.Directory.CreateDirectory(outpath);
Console.WriteLine("Outputting results to \"" + outpath + "\"");
int files_updated = 0;
int total_occurences = 0;
foreach (string file in files)
{
Console.WriteLine("Processing \"" + file + "\"...");
byte[] data = File.ReadAllBytes(file);
string out_file = file.Replace(args[0], outpath);
Console.WriteLine("\tSaving results to \"" + out_file + "\"...");
int occurences_replaced = 0;
while(Replace(ref data, ":qBt-savePath", args[1], args[2]))
{
++occurences_replaced;
}
while (Replace(ref data, ":save_path", args[1], args[2]))
{
++occurences_replaced;
}
if (occurences_replaced > 0)
{
File.WriteAllBytes(out_file, data);
++files_updated;
total_occurences += occurences_replaced;
Console.WriteLine("\tDone, replaced " + occurences_replaced.ToString() + " occurences");
}
}
Console.WriteLine("Updated " + files_updated.ToString() + " files and " + total_occurences + " total occurences");
}
}
}
4) Compile it (Build Solution), you should find a .exe in your project folder
5) Open a command prompt in the folder with the .exe
6) Issue the command (once for each download folder!)
Code: Select all
qBTConvert.exe C:\Users\<YourUser>\AppData\Local\qBittorrent\BT_backup <your windows download directory without \ at the end> <your linux download directory without / at the end>
e.g.:
Code: Select all
qBTConvert.exe C:\Users\grasmanek94\AppData\Local\qBittorrent\BT_backup V:\downloads /data/torrents/downloads
qBTConvert.exe C:\Users\grasmanek94\AppData\Local\qBittorrent\BT_backup U:\downloads /data/torrents/downloads
7) Move everything in
C:\Users\<your user>\AppData\Local\qBittorrent\BT_backup\out to
/home/<your linux qbittorrent user>/.local/share/data/qBittorrent/BT_backup
8 ) Copy all torrent files from
C:\Users\<your user>\AppData\Local\qBittorrent\BT_backup to
/home/<your linux qbittorrent user>/.local/share/data/qBittorrent/BT_backup
9) Start qBittorrent on Linux, everything should be back like it was, remember to recreate any categories before you do all these steps!
10) That's it, no need to recheck your torrents