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 N
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]}"' \;