Search code examples
regexbashshellrenamebatch-rename

Changing filename date format


I have some files that are not recognised by filebot because they have the following naming scheme.

SOAP 3rd Oct 2018 part 1 1080p (USER) [GROUP].mp4

(Name changed)

Filebot does however recognize this naming scheme and needs

SOAP 2018 10 01 Part 1 (USER) [GROUP].mp4

I need a script that can rename these files according to that date format. I have tried reading up on regular expressions but it is going straight over my head. I want to understand how this can be solved.


Solution

  • Use read from a here-string to parse the filename into fields, then use date to reformat.

    Updated to handle spaces between elements before the date.

    $: for f in *mp4
       do IFS='!' read a date b <<< "$( echo "$f" | sed -E '
            s/^(.+) ([0-9]{1,2})[snrt][tdh] ([JFMASOND][aepuco][nbrylgptvc]) ([0-9]{4}) (.*)/\1!\3-\2-\4!\5/' )"
          newName="$( date -d "$date" +"$a %Y %m %d $b" )"
          echo "'$f' -> '$newName'"
          mv "$f" "$newName"
          ls -1 "$newName"
       done
    'Coronation Street 2nd Nov 2018 part 2 1080p (Deep61) [WWRG].mp4' -> 'Coronation Street 2018 11 02 part 2 1080p (Deep61) [WWRG].mp4'
    'Coronation Street 2018 11 02 part 2 1080p (Deep61) [WWRG].mp4'
    'SOAP 3rd Oct 2018 part 1 1080p (USER) [GROUP].mp4' -> 'SOAP 2018 10 03 part 1 1080p (USER) [GROUP].mp4'
    'SOAP 2018 10 03 part 1 1080p (USER) [GROUP].mp4'
    

    Note that I use single quotes inside my echo, and ls puts them around its output, but they are not part of the name of the file.


    ### Update two years later -

    I never liked spawning that read/sed pair on every iteration of the loop. If you had a a couple hundred thousand files, that would get intolerably slow. Here's the kernel of an alternative.

    for f in *mp4
    do if [[ "$f" =~ ^(.+)\ ([0-9]{1,2})[snrt][tdh]\ ([JFMASOND][aepuco][nbrylgptvc])\ ([0-9]{4})\ (.*) ]]
       then echo "with Bash Match: "
            newName="$( date -d "${BASH_REMATCH[3]}-${BASH_REMATCH[2]}-${BASH_REMATCH[4]}" +"${BASH_REMATCH[1]} %Y %m %d ${BASH_REMATCH[5]}" )"
            echo "oldName:'$f' -> newName:'$newName'"
       else echo skipping "'$f'"
       fi
    done