How To: Moving Library locations without losing metadata #6924
-
Update October 2022@MMMZZZZ has a python script that can do the migration. Script can be found here: https://github.com/MMMZZZZ/Jellyfin-Migrator He definitely dug a lot deeper into the db structure than I did. Going with his script is probably the safer method. See his comment here for details on what my guide below misses: #6924 (comment) Original GuideThis is a guide going over how to move the location of your library files without losing all the metadata you've built it. This might not be the right or best way but it worked for me. This is basically a more detailed version of this reddit thread. Leave a comment if you know a better way! I did this on an Ubuntu 20.04 running Jellyfin 10.7.7 in Docker. The ProblemI had all of my library files split over two external drives. The drives were mounted at:
Each mount contained the folders # -r means recursive and -v shows what file it's currently copying over
cp -r -v /media/VolumeOne/TVShows/* /media/Volume5TB/TVShows/
cp -r -v /media/VolumeOne/Movies/* /media/Volume5TB/Movies/
cp -r -v /media/VolumeTwo/TVShows/* /media/Volume5TB/TVShows/
cp -r -v /media/VolumeTwo/Movies/* /media/Volume5TB/Movies/So everything is migrated over. Now I have a problem. How do I keep all that metadata I've built up in Jellyfin? Migrating Library MediaThere are two places where things need to be updated to point to the new drive. The first is in the database and the second is in Jellyfin's config files. 1. Make A BackupI fucked up many times doing this and the only thing that saved me was having a backup. Have this ready in case you mess up and want to reset everything back to its last known working state.
Now that you made your backup let's start messing around with Jellyfin's data. 2. Updating DatabaseI used DB Browser for SQLite to connect to the database file and run queries. The file you need to connect to, located in Jellyfin's There are two tables that need to be updated: The queries for both are similar. Both tables have a -- TypedBaseItems table
-- VolumeOne
UPDATE TypedBaseItems SET
Path = replace(Path, '/media/VolumeOne/TVShows', '/media/Volume5TB/TVShows')
WHERE
Path LIKE '/media/VolumeOne/TVShows%';
UPDATE TypedBaseItems SET
Path = replace(Path, '/media/VolumeOne/Movies', '/media/Volume5TB/Movies')
WHERE
Path LIKE '/media/VolumeOne/Movies%';
-- VolumeTwo
UPDATE TypedBaseItems SET
Path = replace(Path, '/media/VolumeTwo/TVShows', '/media/Volume5TB/TVShows')
WHERE
Path LIKE '/media/VolumeTwo/TVShows%';
UPDATE TypedBaseItems SET
Path = replace(Path, '/media/VolumeTwo/Movies', '/media/Volume5TB/Movies')
WHERE
Path LIKE '/media/VolumeTwo/Movies%';
-- mediastreams table
-- VolumeOne
UPDATE mediastreams SET
Path = replace(Path, '/media/VolumeOne/TVShows', '/media/Volume5TB/TVShows')
WHERE
Path LIKE '/media/VolumeOne/TVShows%';
UPDATE mediastreams SET
Path = replace(Path, '/media/VolumeOne/Movies', '/media/Volume5TB/Movies')
WHERE
Path LIKE '/media/VolumeOne/Movies%';
-- VolumeTwo
UPDATE mediastreams SET
Path = replace(Path, '/media/VolumeTwo/TVShows', '/media/Volume5TB/TVShows')
WHERE
Path LIKE '/media/VolumeTwo/TVShows%';
UPDATE mediastreams SET
Path = replace(Path, '/media/VolumeTwo/Movies', '/media/Volume5TB/Movies')
WHERE
Path LIKE '/media/VolumeTwo/Movies%';You can verify everything worked by running these queries and seeing zero records returned: SELECT COUNT(*) FROM TypedBaseItems
WHERE
Path LIKE '/media/VolumeOne%' OR
Path LIKE '/media/VolumeTwo%'
SELECT COUNT(*) FROM mediastreams
WHERE
Path LIKE '/media/VolumeOne%' OR
Path LIKE '/media/VolumeTwo%'Once you've updated everything in those two tables you can move on to updating Jellyfin's local config files. 3. Updating Jellyfin Config FilesThe following files need to be updated.
|
Beta Was this translation helpful? Give feedback.
Replies: 7 comments 22 replies
-
|
I'll add in some input here, inside the |
Beta Was this translation helpful? Give feedback.
-
|
I'll add as well that this does move most data, but certainly isn't perfect for consolidating two folders and some history is likely lost. If you run you'll see that the folders are now duplicated in the database. Jellyfin, on launch, will log I've made a brief attempt at consolidating them and added it to my existing tutorial on it (which uses a bunch of search and replace commands). I still haven't been able to master what I'm missing on consolidating things in the database. Currently the last step results in things not working when consolidating folders, but likely works fine if renaming folders. I welcome anyone who knows more than me about this to help fix the final database consolidation so we can have clean silent-to-Jellyfin migrations. 1. Shutdown Jellyfin 2. Move all data across to the new hard drive 3. If applicable, change your mapped paths/docker volume maps 4. Update paths in on-disk files: 5. If you consolidated two folders (instead of moved them separately), you'll find that you may have two ./root/default//.mblink files in the same folder pointing to the same place. In this case I had "Documentaries1.mblink" and "Documentaries.mblink". Delete one of the duplicates. 6. Update paths in the database: 7. Update the paths in AggregateFolder entity manually 8. You'll need to manually update the NetworkPath entries in ./root/default/*/options.xml or do so via the interface after startup 9. If you're consolidating two folders like I was, you'll want to manually edit ./root/default/*/options.xml and remove duplicate MediaPathInfo entries. 10. Consolidate IDs in the database to avoid a full rescan of your database and removal of everything on launch 10A. View the duplicate parent IDs that we need to consolidate ###WARNING### NOT YET COMPLETED/WORKING/TESTED |
Beta Was this translation helpful? Give feedback.
-
|
The suggestions here are not wrong but not complete either (which is why it doesn't survive a library scan). I wrote a script that - at the time of writing - successfully migrated the Windows installations of two jellyfin users to Docker without any data loss. While I'd consider the various comments in the script as the better documentation, I thought I'd put a quick overview here since this topic might be linked elsewhere. The reason you can't really do it by hand is because the IDs jellyfin uses throughout its database and file paths which uniquely identify every element of the library are in fact derived from the file paths of said elements. Basically a hash of it. So you not only need to update all the file paths but also all the IDs of all elements and all their occurences. These also occur in jellyfins internal metadata file paths, so those must be reorganized, too. Finally, here's the link. I don't claim it to be the cleanest piece of software but it's fairly well documented and commented I think. @taylorsilva maybe you could update your post...? Kind regards, |
Beta Was this translation helpful? Give feedback.
-
What I did on my Linux server was to copy the files to the new drive, but keep the folder structure. When the copying is complete, I unmount the old drives, delete the old folders which are now empty (because the drives are unmounted) in /media and create symlinks in Now jellyfin should work as before. No reconfiguring needed. |
Beta Was this translation helpful? Give feedback.
-
|
See issue #9922, would it make sense for Jellyfin to implement a "move" action which handles the metadata update concerns while delegating the file system operations to the user? |
Beta Was this translation helpful? Give feedback.
-
|
I don't know if any new solutions came out. But in my case I would love to be able to simply move one of my tv shows to another folder on another hard drive. Am I correct that as of now, this is not simple to do? (Ie. I add the new hard drive path to the library, and then move the tv show to it) I tested it out and jellyfin just removes the show and doesn't register it in the new path. |
Beta Was this translation helpful? Give feedback.
-
|
This issue is pretty old and most of the things described here were working just like that, but it seems not in the recent versions of jellyfin server. My question is the following though. If jellyfin has metadata path, why not just store metadata as a relative path to it? Wouldnt it allow easy migration by simply selecting new metadata path? |
Beta Was this translation helpful? Give feedback.

The suggestions here are not wrong but not complete either (which is why it doesn't survive a library scan). I wrote a script that - at the time of writing - successfully migrated the Windows installations of two jellyfin users to Docker without any data loss. While I'd consider the various comments in the script as the better documentation, I thought I'd put a quick overview here since this topic might be linked elsewhere.
The reason you can't really do it by hand is because the IDs jellyfin uses throughout its database and file paths which uniquely identify every element of the library are in fact derived from the file paths of said elements. Basically a hash of it. So you not only need…