Shell – Move Last Part of Filename to Front

renameshell

I have several files named like this: This is a test - AB12-1998.avi

(the last code is always 2 letters, 2 numbers, dash, 4 digits)

What I'd like to do is rename them like this: AB12-1998 - This is a test.avi

I'd appreciate any solution you can give me using bash, rename, or any other way as long as it gets the job done.

Best Answer

With the Perl rename (*):

rename 's/^(.*) - (.*)(\..*)$/$2 - $1$3/' *.avi

or, if you want to be stricter about the code:

rename 's/^(.*) - ([a-zA-Z]{2}\d{2}-\d{4})(\..*)$/$2 - $1$3/' *.avi

That should work even with names like foo - bar - AB12-1234.avi, since the first .* greedily matches up to the final <space><dash><space>.

(* see: What's with all the renames: prename, rename, file-rename?)

Or similarly in Bash:

for f in *.avi ; do
    if [[ "$f" =~  ^(.*)\ -\ (.*)(\..*)$ ]]; then
        mv "$f" "${BASH_REMATCH[2]} - ${BASH_REMATCH[1]}${BASH_REMATCH[3]}"
    fi
done

Briefly, the regexes break down to

^     start of string
( )   capture group
.*    any amount of anything
\.    a literal dot
$     end of string

Most regular characters match themselves, though you need to escape spaces with backslashes in Bash (as above). The contents of the capture groups appear in order in $1, $2 etc in Perl, and in ${BASH_REMATCH[1]}, ${BASH_REMATCH[2]} etc in Bash.

Related Question