Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a script that is giving me some problems, I know that I have to re-do it recursively but am having some trouble. The script should rename all files and folders in a given folder by removing special characters like $-,)(! and replacing " " with "_"

Here is the piece I need to re-do:

# Rename directories
find "$ORIG_DIR" -name "*" -type d| while read dname
    NEW_DIR=`echo "$dname" |sed -E 's/^[ \t]*//g; s/[ \t]*$//g; s/\./_/g; s/\,/_/g; s/ /_/g'`

        # Rename files
        find "$ORIG_DIR" -name "*" -type f | while read fname
            NEW_FNAME=`echo "$fname" |sed -E 's/^[ \t]*//g; s/[ \t]*$//g; s/\./_/g; s/(.*)_/\1\./; s/\,/_/g; s/ /_/g'`
            if [ -e $NEW_FNAME ]
                echo "$NEW_FNAME already exists. Not replacing $fname"
                echo "Replacing $fname with $NEW_FNAME"
                mv "$fname" $NEW_FNAME

    if [ -e $NEW_DIR ]
        echo "$NEW_DIR already exists. Not replacing $dname"
        echo "Replacing $dname with $NEW_DIR"
        mv "$dname" $NEW_DIR

share|improve this question
Where do you run into troubles with this script? Do you get error messages, does it do something different than expected? – patrix Jan 16 '14 at 22:54
The error message that I get in the end is that there is no such file or directory. This script also won't remove !,$-)( – Erick Jan 17 '14 at 15:54
Well, one problem with the script is that both find commands will always travers the whole directory tree (replace the functionality inside by echo statements to see what's going on). – patrix Jan 17 '14 at 16:00


find . -depth -print0 |
while IFS= read -d '' -r file; do
    dir=$(dirname "$file")
    base=$(basename "$file") 
    base=${base//[[:space:]]/_}         # change whitespace to underscores
    base=${base//[^[:alnum:]_.]/}       # delete any chars not alphanumeric _ .
    if [[ -e $newname ]]; then
        echo "'$newname' exists, not renaming '$file'"
        echo mv "$file" "$newname"

If it looks OK, remove the "echo"

The key here is the "-depth" option to find. It will emit "./sub dir/file name" before "./sub dir". Otherwise if "./sub dir" is renamed to "./subdir", then you'll get a 'file not found' error when the while loops gets to "./sub dir/file name". Also, it means you don't need different logic for directories.

The "-print0" option to find and the busy-ness around the read command are to ensure filenames with spaces are handled properly.

share|improve this answer
This is a good step but it is going too far. It will remove the "." before the file extension which is no good. Also I do want to keep any underscores and have spaces replaced by underscores. Secondly I named the folder in the command, i.e. Folder A, but the script hit all of the folders in the directory containing Folder A. – Erick Jan 17 '14 at 15:50

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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