for f in *.mp4; do
echo mv "$f" \
"$(awk -F '[._]' '{ si = sprintf("%02s", substr($5,2));
print $3 "_" $4 "_s" si "e" $1 "." $6 }' <<<"$f")"
done
- Loops over all
*.mp4
files. - Renames each to the result of the
awk
command, provided via command substitution ($(...)
). - The
awk
command splits the input filename into tokens by.
or "_" (which makes the first token available as$1
, the second as$2
, ...). - First, the number in "_S{number}" is left-padded to 2 digits with a
0
(i.e., a0
is only prepended if the number doesn't already have 2 digits) and stored in variablesi
(season index); if it's OK to always prepend0
, the awk "program" can be simplified to:{ print $3 "_" $4 "_s0" substr($5,2) "e" $1 "." $6 }
- The result, along with the remaining tokens, is then rearranged to form the desired filename.
Note the echo
before mv
to allow you to safely preview the resulting command - remove it to perform actual renaming.
Alternative: a pure bash
solution using a regular expression:
for f in *.mp4; do
[[ $f =~ ^([0-9]+)\._([^.]+)_S([^.]+)\.(.+)$ ]]
echo mv "$f" \
"${BASH_REMATCH[2]}_s0${BASH_REMATCH[3]}e${BASH_REMATCH[1]}.${BASH_REMATCH[4]}"
done
- Uses bash's regular-expression matching operator,
=~
, with capture groups (the substrings in(...)
) to match against each filename and extract substrings of interest. - The matching results are stored in the special array variable
$BASH_REMATCH
, with element0
containing the entire match,1
containing what matches the first capture group,2
the second, and so on. - The
mv
command's target argument then assembles the capture-group matches in the desired order; note that in this case, for simplicity, I've made the zero-padding ofs{number}
unconditional - a0
is simply prepended.
As above, you need to remove echo
before mv
to perform actual renaming.