So we have a problem where we need to crawl through hundreds of thousands of images and rename all of them to comply with ASCII standards. After doing a lot of research online,
I guess this would be better:
find . -type f -exec bash -c 'for f do d=${f%/*} b=${f##*/} nb=${b//[^A-Za-z0-9._-]/_}; [[ $b = "$nb" ]] || echo mv "$f" "$d/$nb"; done' _ {} +
find will find all files (-type f), pass them as positional arguments to this Bash snippet:
for f do
d=${f%/*} b=${f##*/} nb=${b//[^A-Za-z0-9._-]/_}
[[ $b = "$nb" ]] || echo mv "$f" "$d/$nb"
done
We split the filename into dirname d and basename b. We use parameter expansions to replace all the unwanted characters with underscores and save that expansion into variable nb. We check that the expansions $b and $nb are distinct (so as to avoid an error with mv), and if they are distinct, perform the renaming.
I left echo so that nothing is actually performed, the commands are only echoed. Remove the echo if it looks good.
Note that this can overwrite files, e.g., files a&b and a_b.