Shell – How to exchange words in a filename using the shell

greprenamesedshell

One of my customers is a school. On their file server all projects have a directory with the same naming scheme.

<last name>, <first name> <second name>? - <project description>

For example:

Miller, John Andrew - Long project description
Willis, Bruce - Description, perhaps with comma
Lewis, Mary-Jane - Description - Including minus

The new naming convention is:

<first name> <second name>? <last name> - <project description>

For example:

John Andrew Miller - Long project description
Bruce Willis - Description, perhaps with comma
Mary-Jane Lewis - Description - Including minus

Now how to batch rename all existing folders to the new convention?

Best Answer

Since the description part of the filename can contain the pattern - (a hyphen between two spaces), you can change that to some symbol that doesn't occur in the description part. I chose £, but that's purely arbitrary.

rename 's/ - /£/' *
rename 's/([^,]*), ([^£]*)£/$2 $1 - /' *

s/ - /£/' tells rename to replace the first instance of - it finds with£. The second command is a bit more complicated. Parenthases (()) are used to group selections together -- so everything that matches the pattern within the first set of parens can be called later as$1(all the way up to$9).[^,]means 'any character, except for,';means 'zero or more of the previous character';[^,]` means 'zero or more of any character except for a comma'. Since rename is greedy by default, it matches the longest string possible.

The rest, I think, follows pretty naturally.

If you're not sure whether a symbol appears anywhere in the filename, just run:

printf '%s\n' *£*

If you have perl-rename:

rename 's/([^,]*), (.*) - /$2 $1 - /' *

This will break if the description part of the filenames contain - (that is, a - between two spaces).

You should test this with the -n flag, which won't rename any files, but will show what it would have done:

rename -n 's/([^,]*), (.*) - /$2 $1 - /' *
Related Question