Hello again,
I have had another go at this one....
Using find might not work because if you change the names of some directories half way through the search, I guess it can confuse find, possibly missing some files, therefore if you want a recursive algorithm, you should use a script with a for loop.
DISCLAIMER: I am not a bash expert... I am still learning every day. I have done a
small amount of testing on this script and it seems to work on the few test cases I have tried, but recursive scripts that modify the filesystem are powerful tools to be used with care, so don't run this as root, and if the data is important, back it up first. If there are problems though, I will be happy to try to fix them, but I can't recover any lost data!
Code:
bad='[^A-Za-z0-9_.-]'
f() {
for i in *
do
echo $i | grep $bad &&
new=`echo $i | sed s/$bad/_/g` && mv -i "$i" "$new" &&
i=$new
[ -d $i ] && [ ! -s $i ] cd $i && f && cd ..
done
}
f
Description: the first line specifies which characters are not allowed. Next a function f() is declared. This function lists all the files and directories in the pwd. It then greps each filename $i to see if it contains a bad character. If so, it calculates $new (the new filename), performs a move (asks before overwriting), and then updates $i to the new name. Then it checks if $i is a directory (but skip symbolic links) and if so, cd's into the directory and calls itself recursively. By skipping symbolic links, it hopefully won't go into an infinite loop, but I may have overlooked something. The last line calls the function that was jsut declared, starting at the current directory.
I used && instead of ;'s and if fi blocks. You may find this hard to read. Sorry! I'm sure this code could be cleaned up a bit and it can definitely be made more readable! Improvements are
very welcome, I would be happy to see alternative ways to do this.
I hope this is at least be something you can work from. Let me know how you get on.
Happy Bashing!
Mark.