Reputation: 343
I have a lot of files I want to rename and it would take me a long time to do them manually. They are video files and are usually in this format - "NAME OF SHOW - EPISODE NUMBER - EPISODE NAME", so for example "Breaking Bad - 101 - Pilot".
What I would like to do is change the "101" part to my own convention of "S01E01". I figure that in one series of a show the only sequential part of that string is the last number, ie. S01E01, S01E02, S01E03, S01E04 etc...
Would anyone be able to give me advice on how to do this on terminal on Mac OS X. I believe it is too complicated to do with Automator or other batch renaming programs...
Thanks
Upvotes: 1
Views: 1331
Reputation: 45536
Using the perl
rename
implementation which easily can take care of proper padding and works for any number of seaons and episodes (<100, but can easily be adapted to your current format):
$ ls -1 *.avi
My Show - 0301 - Qux.avi
My Show - 101 - Foo.avi
My Show - 102 - Bar.avi
My Show - 1102 - Blah.avi
My Show - 201 - Quux.avi
$ rename -n 's/- (\d+)(\d{2,}) -/sprintf("- S%02dE%02d -", $1, $2)/e' *.avi
My Show - 0301 - Qux.avi renamed as My Show - S03E01 - Qux.avi
My Show - 101 - Foo.avi renamed as My Show - S01E01 - Foo.avi
My Show - 102 - Bar.avi renamed as My Show - S01E02 - Bar.avi
My Show - 1102 - Blah.avi renamed as My Show - S11E02 - Blah.avi
My Show - 201 - Quux.avi renamed as My Show - S02E01 - Quux.avi
I think homebrew
ships with the correct version, so it's just a matter of installing via
$ brew install rename
Upvotes: 0
Reputation: 11
The following script will find all .mp4 with one string of 3 consecutive numbers. Example something.111.mp4 . It will convert it to something.S01E11.mp4 . It will also exclude any sample files.
find . ! -name "*sample*" -name '*.[0-9][0-9][0-9].*.mp4' -type f | while read filename; do mv -v "${filename}" "`echo $filename | sed -e 's/[0-9]/S0&E/;s/SS00E/S0/g'`";done;
Like the previous script it will only work if less than 10 seasons.
For those that are trying to personalize for their current directory tree, I would recommend learning the sed and find command. They are pretty powerful, are simple, and will allow you to substitute any string within a file name.
Upvotes: 1
Reputation: 437100
The following solution:
107
for season 1, episode 7, or 1002
for season 10, episode 2)find
and bash
techniques, such as:
-regex
primary to match filenames by regular expression (rather than wildcard pattern, as with -name
)execdir
to execute a command in the same directory as each matching file (where {}
contains the matching file name only)bash
script that demonstrates regular-expression matching with =~
and capture groups reported via the built-in ${BASH_REMATCH[@]}
variable; command substitution ($(...)
) to left-pad a value with zeros; variable expansion to extract substrings (${var:n[:m]}
).# The regular expression for matching filenames (without paths) of interest:
# Note that the regex is partitioned into 3 capture groups
# (parenthesized subexpressions) that span the entire filename:
# - everything BEFORE the season+episode specifier
# - the season+episode specifier,
# - everything AFTER.
# The ^ and $ anchors are NOT included, because they're supplied below.
fnameRegex='(.+ - )([0-9]{3,4})( - .+)'
# Find all files of interest in the current directory's subtree (`.`)
# and rename them. Replace `.` with the directory of interest.
# As is, the command will simply ECHO the `mv` (rename) commands.
# To perform the actual renaming, remove the `echo`.
find -E . \
-type f -regex ".+/${fnameRegex}\$" \
-execdir bash -c \
'[[ "{}" =~ ^'"$fnameRegex"'$ ]]; se=$(printf "%04s" "${BASH_REMATCH[2]}");
echo mv -v "{}" "${BASH_REMATCH[1]}S${se:0:2}E${se:2}${BASH_REMATCH[3]}"' \;
Upvotes: 1
Reputation: 5412
for FOO in *; do mv "$FOO" "`echo $FOO | sed 's/\([^-]*\) - \([0-9]\)\([0-9][0-9]\)\(.*\)/\1 - S0\2E\3\4/g'`" ; done
This works if there are less than 10 seasons.
Upvotes: 0