简体   繁体   English

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

[英]Recursively rename files to ASCII Standard

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. 因此,我们遇到了一个问题,我们需要抓取成千上万个图像并将其全部重命名以符合ASCII标准。 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命令中,以便在我们的主图像目录中运行:

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" 我得到的最接近的是上面的代码,抛出了很多“ MV:目标filename不是目录”

So can anyone help with this ? 那么有人可以帮忙吗?

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: 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

We split the filename into dirname d and basename b . 我们将文件名分为dirname d和basename b We use parameter expansions to replace all the unwanted characters with underscores and save that expansion into variable nb . 我们使用参数扩展将所有不需要的字符替换为下划线,并将该扩展保存到变量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. 我们检查扩展$b$nb是否不同(以避免mv错误),如果它们不同,则执行重命名。

I left echo so that nothing is actually performed, the commands are only echoed. 我离开了echo因此实际上什么也没做,仅回显命令。 Remove the echo if it looks good. 如果看起来不错,请删除echo

Note that this can overwrite files, eg, files a&b and a_b . 请注意,这可能会覆盖文件a&ba_b

Put this in a shell script, say fixname.sh: 把它放在一个shell脚本中,说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:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM