将文件递归重命名为 ASCII 标准

Recursively rename files to ASCII Standard

所以我们遇到了一个问题,我们需要抓取数十万张图片并重命名所有图片以符合 ASCII 标准。在网上做了很多研究之后,我们找到了这段方便的代码:

mv 'file' $(echo 'file' | sed -e 's/[^A-Za-z0-9._-]/_/g')

来源:How to remove invalid characters from filenames

我已经尝试将它合并到一个递归查找命令中,成为 运行 而在我们的主图像目录中:

find . -print0 | xargs -0 mv $(echo | sed -e 's/[^A-Za-z0-9._-]/_/g')

但我似乎无法将其设置为 运行。我得到的最接近的是上面的代码抛出了很多“mv:target filename Is not a directory”

所以有人可以帮忙吗?

将其放入 shell 脚本中,比如 fixname.sh:

#!/bin/sh

dir=$(dirname "")
name=$(basename "")

newname=$(echo "$name" | sed -e 's/[^A-Za-z0-9._-]/_/g')
if [ "$name" != "$newname" ]; then
    if [ ! -e "$newname" ]; then
        mv "" "$dir/$newname"
    else
        echo >&2 "$newname already exist for "
    fi
fi

然后像这样使用查找:

find . -type f -exec sh fixname.sh {} \;

我想这样会更好:

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 将找到所有文件 (-type f),将它们作为位置参数传递给此 Bash 片段:

for f do
    d=${f%/*} b=${f##*/} nb=${b//[^A-Za-z0-9._-]/_}
    [[ $b = "$nb" ]] || echo mv "$f" "$d/$nb"
done

我们将文件名拆分为目录名 d 和基本名 b。我们使用参数扩展将所有不需要的字符替换为下划线,并将该扩展保存到变量 nb 中。我们检查扩展 $b$nb 是否不同(以避免 mv 出现错误),如果它们不同,则执行重命名。

我离开了 echo 这样实际上什么也没有执行,命令只是回显。如果 echo 看起来不错,请将其删除。

请注意,这可能会覆盖文件,例如文件 a&ba_b