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.

  • Are there any files with a - in the first part, or is it safe to say ` - ` is a delimiter? – jesse_b May 19 '18 at 17:34

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]}"

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.

  • Rename is the easiest, but rheck that you have the correct rename (The one written by Larry Wall). – ctrl-alt-delor May 19 '18 at 18:53
  • @ctrl-alt-delor thanks for clarifying, I had to use the bash solution as in archlinux the default rename is a different tool; the one by Larry Wall is called perl-rename. – Mark Roi May 20 '18 at 7:00
  • @ikkachu I have now my files in this format: "AB12-1998 - This is a test.avi" and have to change them so that the year comes before, e.g. "1998-AB12 - This is a test.avi" - How do I change your bash solution to do that? – Mark Roi May 23 '18 at 8:43
  • @MarkRoi, Well, it's shouldn't be too hard to modify the above to that. I'd suggest you try it. I added a really short explanation of the special characters I used, and there's a number of resources online about regexes, e.g. regular-expressions.info, regex101.com, even wikipedia – ilkkachu May 23 '18 at 9:21
  • @ikkachu Thanks for the extra info. I already tried changing it myself and failed, regex's are really out of my comprehension. I finally managed to do it using awk's substr function. – Mark Roi May 23 '18 at 10:49

Using /bin/sh:

for name in *.avi; do
    n=${name%.avi}    # name without filename extension
    first=${n%% - *}  # first part of name
    last=${n#* - }    # last part of name
    new="$last - $first.avi"  # recombined new name

    printf 'Would move "%s" to "%s"\n' "$name" "$new"
    # mv -- "$name" "$new"

The ${parameter%%word} removes the longest suffix string matching word from $parameter, while ${parameter#word} removes the shortest prefix string matching word from $parameter. The code will therefore swap the two sub-strings on the first occurrence of - (space-dash-space).

Remove the commended out mv to actually rename files.

In comments to ilkkachu's answer, I see that you want to swap the first part of the name as well, so that AB12-1998 becomes 1998-AB12.

Since we're now doing two swap operations on the name, we can put that into a function:

swap () {
    # swaps the two part of a string around
    # the swap point is defined by the first argument



    printf '%s%s%s\n' "$last" "$swstr" "$first"

for name in *.avi; do
    n=$( swap ' - ' "$n" )
    first=${n%% - *}
    first=$( swap '-' "$first" )
    new="$first - ${n#* - }.avi"

    printf 'Would move "%s" to "%s"\n' "$name" "$new"
    # mv -- "$name" "$new"

Example output:

Would move "This is a test - AB9-1995.avi" to "1995-AB9 - This is a test.avi"
Would move "This is a test - AB9-1996.avi" to "1996-AB9 - This is a test.avi"
Would move "This is a test - AB9-1997.avi" to "1997-AB9 - This is a test.avi"
Would move "This is a test - AB9-1998.avi" to "1998-AB9 - This is a test.avi"
Would move "This is a test - AB9-1999.avi" to "1999-AB9 - This is a test.avi"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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