I'm trying to figure out how to write this as a "standard" bash script (running on a QNAP), but not sure where to start - I can do it in NodeJS (since I use it all the time for my job), but would really rather have something.

I'm looking for pointers to how to do this rather than an actual script (though don't let that stop you) ;-)

Using the built-in Plex converted files (for compatibility etc) - input to that is a folder tree with various movie files (extensions are most commonly .avi, .mp4 or .mkv), which it then makes into an .mp4 file in a slightly different path.

I want to copy (not move - I'll let Plex clean up its own mess) the Plex output files back over the input files.

Example structure - from...

Plex Versions/Optimized for Mobile/My Tv Show/S01E01.mp4


My TV Show (1990-1995)/Season 1/s01e01 My Episode Name.mkv


  • The root path for both is the same (for my setup, others might have the Plex Versions folder within the My TV Show (1990-1995) folder - this script will go on GitHub when done etc).

  • The TV show name may change. I put the start and end date (or a trailing - if ongoing) in brackets. Plex will use the "official" name, which might have a start year if there is more than one show with the same name.

  • Bearing the above in mind, I may have multiple shows with the same base name, but different years.

  • The target basename will be in the Season x folder (season number without leading 0) and have the same prefix.

  • If it's season 0, then it might instead be in the Specials/ folder (I'll get things consistent at some point).

  • If the original filename had a .mp4 filename, then the copied target file must have a .m4v filename.

  • After copying the new file over, the original file can be removed (leaving the copy source and target files).

If I was doing this in NodeJS I'd do something like the following:

  1. Get a sorted list of TV Show folders (earlier shows don't generally have years while later ones do).
  2. For each folder regex replace end years (/-\d*\)/ to "" to include the start year only, and case insensitive match against the Plex folders. If no match then try with no year.
  3. If no match found go back to 2 and try again.
  4. Get a list of Plex version files that match the pattern /S\d+E\d+\.mp4/ (there can be subtitles included from when I just ripped everything and didn't filter the streams).
  5. For each file get the season number, then search the Season x folder for the same prefix. If it's season 0 then also search the Specials folder.
  6. Replace the extension on the matched name with .mp4, if no replacement done then replace it with .m4v.
  7. Copy the Plex file to the new path+name.
  8. Remove the matched file, then go back to 5.

Now variables for names I can do, same for the obvious unlink - what I'd like help with is -

Best way to make the initial folder match (is 1-3 the best way, or is there a better shortcut? Looking at this one: Copy files to a destination folder only if the files already exist. but the source files have a different file extension )

Checking if a file exists and try different extension combinations if not.

edit: There's over 30tb of files, and Plex does not replace original files (there's been an open request for it since 2015).

2 Answers 2


I would personally suggest using FFmpeg to convert the files within your primary Plex Library folder. Something along the lines of:

set -s globstar;

for f in ./**/*.{avi,mp4,mkv}; do
    ffmpeg -i "$f" -c:a aac -c:v libx264 -preset slow "${f%.*}_b.mp4"
    rm "$f"
    mv "${f%.*}_b.mp4" "${f%.*}.mp4"

You can also just set Plex to store your optimized version within the directory of the original files.

That being said, this code might do what you're looking for, but it's completely untested:


for DIR in "$Optimized"/*; do
    if [[ -d "$DIR" ]]; then
        SHOW_MATCHES=("$Plex_Main"/*"$(basename "$DIR")"*/)

        # If there is one, and only one, match
        if [[ ${#SHOW_MATCHES[@]} -eq 1 ]]; then
            # The non-optimized show path
            SHOW_PATH="$Plex_Main"/*"$(basename "${DIR[0]}")"*

            for f in "$DIR"/*.mp4; do
                # Remove file extension


                if [[ ${#EP_MATCHES[@]} -eq 1 ]]; then
                    cp "$f" "$SHOW_PATH/${ORIG_FILE%.*}.mp4"
  • I used to use FFMpeg, but I fall into the trap of wanting to keep improving the output (little bit of OCD there) - leaving it up to Plex saves a little bit of my sanity... That looks like a step closer to what I need, but doesn't take into account the changing folder names - without that annoying detail this would be a lot easier - think I need to play with expr when I get home :-)
    – Rycochet
    Commented Apr 18, 2017 at 14:03

You should not automatically use the Plex optimized versions as they could be:

  1. Corrupt
    enter image description here
  2. Washed out
    enter image description here
  3. Without subtitles and/or chapters
    enter image description here
  4. not de-interlaced
    enter image description here
  5. with burned in subtitles in a language that you or an other viewer doesnt want (anymore)

This depends on known bugs or maybe the input does not 100% fit to the needed encoding profile of the transcoding Software or iGPU. So the better method would be to view the optimized versions and replace them individually. Loosing the original file could be a bigger problem than saving storage space. If your target is to save space because of costs, do not forget that re-transcoding so many videos boosts the electricity bill and storage is becoming cheaper and cheaper over time.

And finally most re-transcoding means loosing quality and its not an easy task to find the correct transcoding options fitting your needs of quality and file size.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .