问题
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, we found this handy piece of code:
mv 'file' $(echo 'file' | sed -e 's/[^A-Za-z0-9._-]/_/g')
sourced from: How to remove invalid characters from filenames
I have tried merging it into a recursive find command, to be run whilst in our main images directory:
find . -print0 | xargs -0 mv $(echo | sed -e 's/[^A-Za-z0-9._-]/_/g')
But i cant seem to get it to run. The closest i've gotten, is the above code throwing a lot of "mv: target filename
Is not a directory"
So can anyone help with this ?
回答1:
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
.
回答2:
Put this in a shell script, say fixname.sh:
#!/bin/sh
dir=$(dirname "$1")
name=$(basename "$1")
newname=$(echo "$name" | sed -e 's/[^A-Za-z0-9._-]/_/g')
if [ "$name" != "$newname" ]; then
if [ ! -e "$newname" ]; then
mv "$1" "$dir/$newname"
else
echo >&2 "$newname already exist for $1"
fi
fi
Then use find like so:
find . -type f -exec sh fixname.sh {} \;
来源:https://stackoverflow.com/questions/33055869/recursively-rename-files-to-ascii-standard