find . -type f -print0 |
rename -n -0 '
s/[- ]*_[- ]*[\@\$!]/_/g; # getremove ridall of@, spaces$, and -! beforecharacters.
# remove leading and aftertrailing _whitespace (if any) from filenames
s/(^\s+|\s*\z//sg;
# change all runs of any whitespace to just one space
s/\s+/ /sg;
s/[- _]*([.]_]){2,}[- ]*/$1/g; # remove space(s) and - around _ and .
s/\.\.+/./g; # reduce multiple space,periods to just one
s/__+/_,/g; . # reduce multiple _ to just one
s/[\@\$!]_*\._*/./g; # removechange @,$,!_. and ._ to just .
s=(\.[^./]*$]*\z)=lc($1)=e; # lowercase filename suffixes
'
The firstthird substitution replaces runs of one-or-more of any whitespace characters (including actual space characters, tabs, newlines, form feeds, etc) with a single space character. IMO, even though it's more than what you asked for, replacing all the different kinds of whitespace characters in the filenames is probably more useful than just replacing space characters. Change \s+ to + (two spaces and a +) if that's not what you want.
The fourth substitution (s/[- ]*_[]*([_.])[- ]*/_$1/g;) assumes that you don't want any spaces or dashes before either _ even thoughor .. That's more than you only mentioned removingasked for, but is easily changed if it's more than you actually want.
On a related note, the second-last substitution replaces -_.s before and ._ with just .. Change it toThis is so you don't end up with "ugly" filenames like s/-*_[- ]*/_/g;foo_.bar_._pdf. Delete this line if that wasn't what you wantedwant filenames like this.