Remove special characters and replace space with _ from files and directories Recursively in Bash 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
do
    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
        do
            NEW_FNAME=`echo "$fname" |sed -E 's/^[ \t]*//g; s/[ \t]*$//g; s/\./_/g; s/(.*)_/\1\./; s/\,/_/g; s/ /_/g'`
            if [ -e $NEW_FNAME ]
            then
                echo "$NEW_FNAME already exists. Not replacing $fname"
            else
                echo "Replacing $fname with $NEW_FNAME"
                mv "$fname" $NEW_FNAME
            fi
        done

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

END
Untested

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 _ .
    newname="$dir/$base"
    if [[ -e $newname ]]; then
        echo "'$newname' exists, not renaming '$file'"
    else
        echo mv "$file" "$newname"
    fi
done


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.