3

If I have some TV Shows that are named badly and I need to clean them up

$ ls
Some_Series.1_Episode.1.mp4  'Some Series01.Episode02.mp4' SomeSeries1Episode03.mp4

I need to batch rename them to become

$ ls
S01E01.mp4  S01E02.mp4  S01E03.mp4

I have used the following script and it works but only when the original filenames contain Series and Episode numbers 01 02 03 and not 1 2 3

#!/bin/bash
# rename tv show filenames to be kodi friendly
cd /mnt/2tb_hd/con/
if [ $? == 1 ]; then 
    exit
fi
for filename in *; do
        if [[ "$filename" =~(\**).*(.*[0-9][0-9]).*([0-9][0-9]).*(\....)$ ]]; then
            result=$(echo mv \"$filename\" S${BASH_REMATCH[2]}E${BASH_REMATCH[3]}${BASH_REMATCH[4]}\") 

                if [[ $? == 0 ]] ; then 
                    mv "$filename" "S${BASH_REMATCH[2]}E${BASH_REMATCH[3]}${BASH_REMATCH[4]}"
                fi
            fi
        done
        exit

I need to make this code either change any 1 2 3 4 5 etc in the filenames to have a 0 padding before running the 2nd renaming loop or just alter the code I already have to change either 01 or 1 regardless of the 0 padding.

Sorry if this seems really obvious but I am new to bash so please forgive me.


I have updated the script and now I have issues with episode 8 and 9. I get the following error

line 10: printf: 08: invalid octal number

So episode 8 and 9 are missing but there is one extra file S02E00.mkv for each series with over 7 episodes.

The adapted script

#!/bin/bash
# rename tv show files to kodi friendly format S01E01 etc
cd /mnt/2tb_hd/Adults/TV_Shows/Breaking\ Bad/
if [ $? == 1 ]; then 
    exit
fi
reg='^([^0-9]*)([0-9][0-9]*)[^0-9]*([0-9][0-9]*).*(\....)$'
for filename in *.*; do
      if [[ $filename =~ $reg ]]; then
              printf -v newname 'S%02dE%02d%s' "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}" "${BASH_REMATCH[4]}"
                  mv "$filename" "$newname"
                fi
            done
        exit

See http://pastebin.com/2XRH85ua for the full outcome of the test run.

3

Use printf, with a format string that specifies field width and zero-padding for the integers e.g.

printf -v newname 'S%02dE%02d%s' "$((10#${BASH_REMATCH[2]}))" "$((10#${BASH_REMATCH[3]}))" "${BASH_REMATCH[4]}"

Note the use of $((10#${BASH_REMATCH[n]})) to force decimal evaluation in cases like 09

Testing (I modified your regular expression slightly BTW):

reg='^([^0-9]*)([0-9][0-9]*)[^0-9]*([0-9][0-9]*)(\....)$'
for filename in *.mp4; do
  if [[ $filename =~ $reg ]]; then
    printf -v newname 'S%02dE%02d%s' "$((10#${BASH_REMATCH[2]}))" "$((10#${BASH_REMATCH[3]}))" "${BASH_REMATCH[4]}"
    echo mv "$filename" "$newname"
  fi
done
mv Some Series01.Episode02.mp4 S01E02.mp4
mv SomeSeries1Episode03.mp4 S01E03.mp4
mv Some_Series.1_Episode.1.mp4 S01E01.mp4


Possibly more robust would be to use the regex only to match the first two sequences of digits, and use shell parameter substitution to handle the extension:

reg='([0-9][0-9]*)[^0-9]*([0-9][0-9]*)'
for filename in *.mp4 *.mkv; do
  name="${filename%.*}"
  ext="${filename##*.}"
  if [[ $name =~ $reg ]]; then
    printf -v newname 'S%02dE%02d.%s' "$((10#${BASH_REMATCH[1]}))" "$((10#${BASH_REMATCH[2]}))" "${ext}"
    echo mv "$filename" "$newname"
  fi
done
mv Some Series01.Episode02.mp4 S01E02.mp4
mv SomeSeries09Episode10.mp4 S09E10.mp4
mv SomeSeries1Episode03.mp4 S01E03.mp4
mv Some_Series.1_Episode.1.mp4 S01E01.mp4
mv Breaking.Bad.S01E01.576p.BluRay.DD5.1.x264-HiSD.mkv S01E01.mkv

Alternatively, if your system has the perl-based rename / prename command, you could so something like

prename -vn -- 's/.*(\d+).*(\d+)/sprintf "S%02dE%02d.mp4", $1, $2/e' *.mp4
9
  • Thanks, that seems to be working perfectly now. I'm not sure why you put the echo line in. I removed the echo and just have mv "$filename" "$newname" and it seems to be renaming files containing whitespaces and periods. I still need to fully test it on batches of files but time will tell. Thanks for your help – s7ntax Aug 25 '16 at 20:44
  • It doesn't work on filenames like this 'Breaking.Bad.S01E01.576p.BluRay.DD5.1.x264-HiSD.mkv' could it be the periods or extra numbers in the filename? The problem is that files are always named really badly in an inconsistent way. I have changed the mp4 for mkv in the script. – s7ntax Aug 26 '16 at 11:31
  • @s7ntax try changing the regex to reg='^([^0-9]*)([0-9][0-9]*)[^0-9]*([0-9][0-9]*).*(\....)$' to match (and discard) an extra sequence of arbitrary characters between the second sequence of digits and the extension. – steeldriver Aug 26 '16 at 12:25
  • @s7ntax I've added a variant that I think may be more robust – steeldriver Aug 26 '16 at 12:36
  • OK - just a note, you may want to add the -n or --no-clobber flag to your mv in case there are names that conflict once they are stripped of the other strings – steeldriver Aug 26 '16 at 14:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.