Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

So I have the following shell script for batch renaming the episodes of some given TV series:

#!/bin/bash
#script for renaming files of form "*01*.ext" to "Episode 01.ext";
counter=0
for all_files in * ; do
  counter=$(( $counter+1  )) #increments $counter by 1;
  #creates counter "number" with two digit format (eg: 01):
  if [[ 1 = $(( $counter<10 )) ]] ; then
    number=0$counter
  else
    number=$counter
  fi
  #checks all file names for presence of $number and renames those files:
  for numbered_file in *$number* ; do 
    ext=${numbered_file##*.}
    mv "$numbered_file" "Episode $number.$ext"
  done
done

I now want to improve the script to account for some quite common exceptions. In particular I don't want the "20" in "720p" to be interpreted as referring to "Episode 20". What I want then, is a way to refine the *$number* pattern from the inner for loop. (number is a variable assigned to 01, 02, 03 and so forth.)

How do I achieve something along the lines of:

* no "7" here $number no "0" or "p" here *

Please feel free to point out anything else about the above script that is awkwardly done. It is my first attempt at a vaguely useful script and as such it is probably full of stylistic monstrosities. ;-)

share|improve this question
1  
Your current pattern description is basically "if file name contains episode number". This is very crude since as you have realized already, many things can match episode number without actually being the episode number. Instead of the ad hoc approach of adding exceptions as you run across them for e.g. 720p or 1080p or 2012 or S05E05 etc., you'd probably save some time and effort if you spent some time coming up with a slightly more restrictive general pattern. –  jw013 Sep 19 '12 at 16:35
1  
Would you be adverse to a completely different approach? The production of numbers to match against your files becomes unnecessary with a simple regex and the loops could be replaced by a single find command. –  tojrobinson Sep 19 '12 at 17:05
    
I am mainly using this script for anime shows, which do not necessarily follow any regular behaviour outside the episode number. I suppose I could run the script with an argument so as to manually supply additional information. Another thing that might bee good is having the pattern specifically seek out the first two digit number that appears in the string. But I am not sure how to do that either... –  Psachnodaimonia Sep 19 '12 at 17:07
    
It seems to me that you try to reinvent the wheel. Especially related to the processing of the filenames, that probably share a common pattern. For a task like this you should consider to use a tool that supports regular expressions. It is tedious to do all the text processing only with built-in bash commands. –  user1146332 Sep 19 '12 at 17:08
1  
Please add a representative sample of filenames to your question (obscure/change the names a little if you need to but leave the pattern as is). All we know is that there may be some two-digit numbers somewhere in the filenames, and some of them may have other numbers. That's not really enough to construct a good pattern match with...we don't even know if there IS a usable pattern to the names or if they're completely arbitrary. –  cas Sep 19 '12 at 23:27
show 2 more comments

2 Answers

up vote 2 down vote accepted

It looks like you're re-inventing existing tools like mmv and rename - there are several programs called rename but the one I'm thinking of is the perl rename aka prename (it's included with the perl package in debian and derivatives, possibly other distros too).

I'd provide some examples of usage for both of them but you haven't given us an example of the source file names (see my comment above).


BTW, since your script is bash rather than sh, you can replace your if/then/else for zero-padding $number with the bash-builtin printf like this:

printf -v number "%02d" "$counter"

In POSIX shell, you could use number=$(printf "%02d" $counter) instead. The printf command is part of GNU Coreutils.

share|improve this answer
add comment

Bash has a regexp matching construct:

[[ $string =~ regexp ]]

It's not much help for what you want to do, though. To extract the intersting number from your file name, strip off the boring bits and keep the last non-boring sequence of digits.

shopt -s extglob
number=$filename
number=${number//[0-9][0-9]+([0-9])p}
number=${number%%+([^0-9])}
number=${number##*[^0-9]}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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