Take the 2-minute tour ×
Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

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
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 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 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 at 16:00

1 Answer 1

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.

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 at 15:50

Your Answer

 
discard

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.