Batch Rename – Bash Script to Remove/Change Illegal Characters in Windows Filesystem

bashbatch-renamecommand linescripts

I need an assist here, got a project going where we need to modify file & folder names within a specific directory in order to remove or replace any and all characters which would be considered illegal under Windows, with a few additional characters.
Leave final extnsion

ILLEGAL CHARACTERS:

    < (less than)                         MAKE -
    > (greater than)                      MAKE -
    : (colon)                             MAKE -
    " (double quote)                      REMOVE
    / (forward slash)                     MAKE -
    \ (backslash)                         MAKE -
    | (vertical bar or pipe)              MAKE -
    ? (question mark)                     REMOVE
    * (asterisk)                          REMOVE


ADDITIONAL CHARACTERS:

    REMOVE '
    REMOVE %
    REMOVE #
    REMOVE ^
    REMOVE !@#$%^&()=+][{};,`~

Any character with "MAKE -" next to it needs to be made a – (hyphen) in place of the character, for example a file named John\Sykes.doc needs to become John-Sykes.doc.
If the character is flagged as "REMOVE" then it should be removed, and nothing be put in it's place, for example a file named John?Sykes.doc would become JohnSykes.doc

This is a rather important step in a very large project we have going in our organisation, and I haven't been able to create a script thus far. I know how to make simple versions, that can only change file names on a case by case basis but can't do it en mass. For example, I can create a script to remove only @ from file names, but I don't know how to include folders/directories nor do I know how to include all the other characters in this one script.

Ideally the script would run the first time and produce a file using echo with all the changes that need to be made including the full path and then the changed path. The script would then either need to be modified slightly to use mv instead, or it could refer to the file created using echo and perform all the necessary changes using it…

Any and all help would be appreciated as this is really rather important and I lack the skills at this point in time to make this myself…

A final note, I can't use the #rename command. It breaks our IT policy.

EDIT

I'm unable to use any version of rename, the head of my IT dept. has forbade it. I'm sure he has his reasons, but I can't say that I'm privy to them. The rename command is not available on our servers at all.

This means I have to use pure bash to perform the operation.

There aren't any additional requirements. Basically I need to be able to run a script to output all the changes that will be made to a file, before anything is changed. This will allow us to review the results and make sure there are no stuff-ups. After that, we want to run (the same script or a different one) it to actually make the changes.

All I need is stated above, so anything marked "MAKE -" needs to become a hyphen and anything marked "REMOVE" needs to just go away.

If there's anything else, please ask. I'll happily give further comment.

Best Answer

Create a script rename1.sh:

#! /bin/bash
old=$1
new=${old//[\''"?*%#^!@$&()=+[]{};,`~']}
new=${new//['<>:\|']/-}                   # I removed /, see below.
if [[ -e $new ]] ; then
    if [[ $old != $new ]] ; then
        echo Cannot rename "$old" to "$new" - target already exists.
    fi
else
    mv "$old" "$new"
fi

It renames one file according to the given rules using parameter expansion. To rename a subtree, run it with find:

find /path -exec rename1.sh {} \;

Are you sure you want to replace / with -? It would put all the files into the same directory.