Press "Enter" to skip to content

Rtorrent magic: Moving finished torrents based on labels

So… I’ve been using rtorrent as my main torrent client for a couple of years now. I have it running on my server and I’m usually adding torrents either by placing them in a watchdir or by adding them through a web interface (rutorrent, in case you’re wondering).

One of the things I’ve always wanted was to have rtorrent handle multiple categories. I wanted games I downloaded to go into a “games” directory, comics into a “comics” directory, and so on. I’ve been looking for solutions for a few years now, and all I’ve found online are people in the same boat. So today I decided to spend a few hours experimenting… And this is the result.

The Solution

UPDATE 2022-07-07: Added updated code for rTorrent 0.9.6 at the end of the post!

My way of doing this uses two lines of code in .rtorrent.rc:

# Add new method to get finished dir
system.method.insert = d.get_finished_dir,simple,"cat=[folder]/finished/,$d.get_custom1="
# Bind event "torrent has finished" to action "move to new directory based on label"
system.method.set_key = event.download.finished,move_complete,"d.set_directory=$d.get_finished_dir=;execute=mkdir,-p,$d.get_finished_dir=;execute=mv,-u,$d.get_base_path=,$d.get_finished_dir="

The first line, the system.method.insert thing, basically says that each torrent object should be able to return a string which is the concatenation of “[folder]/finished/” and the torrent’s label. So a torrent with the label “tvshows” will return “[folder]/finished/tvshows”. Change the first part to whatever you want your base “finished torrents” directory to be. I haven’t tried this with any directories containing spaces, but I’m guessing escaping would be the way to go.

The second line basically says that the torrent should set its internally defined directory to whatever get_finished_dir returns, then create the directory if it doesn’t already exist, and finally move the torrent to the same directory.

  • Torrents without labels will be placed in the base dir.
  • Torrents with labels corresponding to already existing folders will be moved to those folders.
  • Torrents with labels corresponding to folders that don’t already exist will have the folder created for them, then they’ll be moved to that folder.

It’s a bit complex, but hopefully my explanation makes thing a bit clearer =)

TL;DR: Insert the lines in your .rtorrent.rc, replace [folder]/finished/ with your base directory for finished torrents.

Watch directories

I have set up several watch directories, each corresponding to a category or label.

# TV shows
schedule = watch_directory_1,5,60,"load_start=[folder]/input/tvshows/*.torrent,d.set_custom1=tvshows"

# Movies
schedule = watch_directory_1,5,60,"load_start=[folder]/input/movies/*.torrent,d.set_custom1=movies"

# Comics
schedule = watch_directory_1,5,60,"load_start=[folder]/input/comics/*.torrent,d.set_custom1=comics"

# Music
schedule = watch_directory_1,5,60,"load_start=[folder]/input/music/*.torrent,d.set_custom1=music"

There are two important parts of each of these lines. The [folder]/input/x part is the directory to be watched. The last part, after set_custom1=, is the label torrents found in the directory will be assigned.

This means when I’m downloading a movie, say, then I put the torrent in the [folder]/input/movies folder. It’s automatically added to rtorrent, with the label “movies”. When finished, it’s placed in [folder]/finished/movies.

Next step for me will be to add some automatic fetching of subtitles for downloaded movies and tv shows, but I’m pretty happy with this setup…

Update #1 (old)

I recently upgraded to rTorrent 0.6.9. Slight change as shown below:

# Add new method to get finished dir
method.insert = d.get_finished_dir,simple,"cat=[folder]/finished/,$d.get_custom1="
method.set_key = event.download.finished,move_complete,"d.set_directory=$d.get_finished_dir=;execute=mkdir,-p,$d.get_finished_dir=;execute=mv,-u,$d.get_base_path=,$d.get_finished_dir="

I haven’t tested this extensively, though. I might come back to revise this further.

Update #2 (2022-07-07): rTorrent 0.9.6

I’ve switched to Flood as my interface and upgraded rTorrent, which meant I had to change some stuff. I’ve ditched the Watch Directories

This is what I have in my current .rtorrent.rc:

# Add new method to get finished dir (called get_finished_dir)
method.insert = d.get_finished_dir,simple,"cat=[folder]finished/,$d.custom1="

# Bind event "torrent has finished" to action "move to new directory based on label"
method.set_key = event.download.finished,move_complete,"d.directory.set=$d.get_finished_dir=;execute=mkdir,-p,$d.get_finished_dir=;execute=mv,-u,$d.base_path=,$d.get_finished_dir="

The changes are marked in bold. Remember to change [folder] to the folder where you want your torrents to go! I just don’t want to inform the entire internet exactly where on my server I keep stuff =)

Here’s also a more detailed breakdown of what the second line does (mostky for my own sake, so I don’t forget):

  • method.set_key = event.download.finished,move_complete | Modifies the event.download.finished event to also have a new “key” called “move_complete”. From what I understand, rTorrent executes all “keys” in an event whenever that event is fired. The event.download.finished event fires whenever a torrent has finished downloading. The stuff within the quotation marks is the new key’s commands. Each command is separated by a semicolon (;).
  • d.directory.set=$d.get_finished_dir=; | d.directory.set sets the directory of the torrent in rTorrent’s own information. It does not move the torrent, just means rTorrent will look in that directory from now on. $d.get_finished_dir just runs the get_finished_dir method preciously inserted; constructing a path name by combining [folder]/finished/ with whatever label was applied ($d.custom1 contains the label).
  • execute=mkdir,-p,$d.get_finished_dir=; | Gets the same path name and makes sure the directory actually exists. Mkdir is the standard *nix command for creating directories. -p means creating parent directories if needed and not complaining if directory already exists.
  • execute=mv,-u,$d.base_path=,$d.get_finished_dir= | Uses the same “execute” functionality as above to run the standard *nix mv command to move the torrent’s files (whose location is stored in d.base_path) to, once again, the directory whose name was constructed by the get_finished_dir method.

What happened between versions was basically that some of rTorrent’s internal scripting commands changed: d.get_custom1 became just d.custom1, and d.set_directory became d.directory.set.

Thanks to commenter “rTorrenter” for the new commands, worked like a charm. For me, at least.

Sources

I borrowed the method.insert stuff from this recipe.

The custom1 and label stuff I found in several places, but this solution is basically what I based mine on. I can’t seem to find the page where I found the information that the rutorrent labels are the same as d.get_current1 though.

I know there are addons for rutorrent (like autotools) that do similar things, but I wanted a server-based solution.

Got a better solution? Let me know and I’ll update this post & give credit!

23 Comments

  1. Dave Dave August 27, 2014

    Hi. Thanks for this. If I wanted to midofy it to make all downloads with no label to go to “/Other”, how would I do that?

  2. Jeremy Jeremy March 11, 2015

    Thanks, this helped a lot!
    One issue, tho, that I had to sort out…
    you can only use “watch_directory_1” one time as each subsequent use overrides the previous one. So in your example, it should be
    TV Shows line – schedule = watch_directory_1,5,60 etc
    Movies line – schedule = watch_directory_2
    Comics line – schedule = watch_directory_3
    etc etc

  3. Jon Jon April 19, 2015

    Hello, I really, really enjoy your code. It does so much more for me than you will ever know. I do have a follow up question/request if you would be willing to help me out. How would the code read if I wanted the following to happen. When I assign the torrent a label, lets say for example ” Always seed TVHD” how could I get it to put into a directory automatically that would be setup like this, which basically is just one more folder then you have, downloads/finished/Always_Seed/TVHD the first director is of course the default location of where all my torrents go to. This is a another example of the same thing, lets say I want to label a torrent “Seed to 1 TVHD” and it download automatically to a folder located here downloads/finished/Seed_to_1/TVHD. Basically I am just adding in a extra folder that was spoken of in your script and wondering how to do this,

    • krank krank April 23, 2015

      Sorry, I haven’t really been tinkering much with this code as of late. I’ve forgotten most of it, and anyways part of it stopped working and I just gave up on the whole thing. Sorry I can’t help you!

  4. Me Me May 23, 2015

    Hey, this works in Debian Jessie’s rtorrent (0.92/0.13.2) and latest ruTorrent. Thanks for the tip.

  5. guest123 guest123 June 20, 2015

    Thank you for this!

  6. chnateag chnateag July 9, 2015

    Where is this guys ? LET ME PAY HIM A BEER !!

  7. guest12311 guest12311 July 20, 2015

    Thank you for posting this

  8. kevin kevin August 30, 2015

    this is awesome, thank you!

  9. cdtkoenig cdtkoenig December 12, 2015

    Hi,

    excelent hack !! 🙂
    I use autotools which work fine with watch folders (populated by sickrage and couchpotatoe) but not at all using rutorrent web GUI manual labelling.
    Is this solution compatible with autotools in order to manage manual and automatic labelling ?
    I’am afraid not …
    Thx

    • krank krank March 8, 2016

      I have no idea, sorry… Haven’t used autotools myself.

  10. Ricardo Nunes Ricardo Nunes March 26, 2016

    Hello,

    This method still works?
    I added the two lines in .rtorrent.rc but did nothing.

    Do I have to restart the server? is necessary to change something more?

    Thank you,

    • krank krank March 26, 2016

      It should work, provided rtorrent is restarted. I’m using it myself. It’s possible there’s some version of rTorrent it doesn’t work with; I haven’t upgraded in forever…

  11. Ricardo Nunes Ricardo Nunes March 27, 2016

    I rebooted the server and it was OK.

    I still have a problem if using a label composed of 2 folders “xpto/xpto” it works but creates a folder “xpto%2Fxpto”

    Can you help?

  12. JM Gant JM Gant October 11, 2016

    this is perfect. excellent piece and a nice introduction to the blog. glad I ground this.

  13. Citrix Citrix December 28, 2019

    Out of interest did you get this working on rTorrent 0.9.8?
    It was working fine on 0.9.6 but since upgrading I have to remove this code otherwise rTorrent doesn’t start.

  14. FasterTorrents FasterTorrents July 12, 2020

    This is what worked for me for rutorrent 3.6

    directory = /defaultdownloadfolder/
    method.insert = d.finished_dir,simple,”cat=/pathtobecopiedto/,$d.custom1=”
    method.set_key = event.download.finished,move_complete,”d.directory=$d.finished_dir=;execute=mkdir,-p,$d.finished_dir=;execute=mv,-u,$d.base_path=,$d.finished_dir=”

  15. rTorrenter rTorrenter January 21, 2021

    This is what worked for me with rTorrent 0.9.8:


    method.insert = d.get_finished_dir,simple,"cat=/path/to/finished/,$d.custom1="
    method.set_key = event.download.finished,move_complete,"d.directory.set=$d.get_finished_dir=;execute=mkdir,-p,$d.get_finished_dir=;execute=mv,-u,$d.base_path=,$d.get_finished_dir="

  16. RTer RTer March 14, 2022

    Hello – I’m having a lot of trouble getting something like this working. I have about a 1000 torrents in my rtorrent 0.9.6 installation (running on unraid). I would like to create a script that allows the save path to dynamically change based on the label assigned. I tried both of the below scripts for a test file that was already downloaded and seeding, but it doesn’t seem to change the save path when I change the label. Does anyone know what I can do to get this working?

    # Add new method to get finished dir
    method.insert = d.get_finished_dir,simple,”cat=/data/,$d.get_custom1=”
    method.set_key = event.download.finished,move_complete,”d.set_directory=$d.get_finished_dir=;execute=mkdir,-p,$d.get_finished_dir=;execute=mv,-u,$d.get_base_path=,$d.get_finished_dir=”

    # Add new method to get finished dir
    method.insert = d.get_finished_dir,simple,”cat=/data/,$d.custom1=”
    method.set_key = event.download.finished,move_complete,”d.directory.set=$d.get_finished_dir=;execute=mkdir,-p,$d.get_finished_dir=;execute=mv,-u,$d.base_path=,$d.get_finished_dir=”

    • krank krank July 7, 2022

      I’m not sure rTorrent scripting actually has the capability of detecting label changes, which is what you’d need. My scripts just hook into the “torrent has finished downloading” event (event.download.finished), which means my stuff just executed when the torrent first finishes downloading.

      From what I can read on https://rtorrent-docs.readthedocs.io/en/latest/cmd-ref.html#event-commands , I can’t find anything about label changes. Maybe some commands could be scheduled? Or one could cheat a little bit, hooking into the paused/resumed events. I’d love to help out more but I just don’t have the time I’m afraid. I tried breaking down how I counstructed by scripts in the new update I posted, maybe that breakdown together with the link above can get you started?

  17. vdias vdias June 10, 2022

    Any update on this?

    • krank krank July 7, 2022

      I just added a new update! Basically I got things working again by using rTorrenter’s solution as posted above.

  18. Alan Alan November 7, 2022

    Is it possible to do so that different label moves the torrent files to different locations?

    For instance,

    I would like the torrents labeled ‘Music’ to be moved to the folder /ssd/Music

    But I want torrents labeled with ‘Movies’ to be moved to /hdd/Movies

    Tack på förhand!

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.