如何从文件名中删除非 ASCII 字符?

RJF*_*ner 7 windows-7 unicode rename filenames batch-rename

我有几个文件名包含各种 Unicode 字符。我想将它们重命名为仅包含“可打印”ASCII 字符(32-126)。

例如,

Läsmig.txt         //Before
L_smig.txt         //After
Mike’s Project.zip 
Mike_s Project.zip 
Run Code Online (Sandbox Code Playgroud)

或为获得奖励积分,转录为最接近的角色

Läsmig.txt
Lasmig.txt
Mike’s Project.zip
Mike's Project.zip
Run Code Online (Sandbox Code Playgroud)

理想情况下,寻找不需要 3rd 方工具的答案。

(编辑:鼓励脚本;我只是想避免需要安装才能工作的利基共享软件应用程序)


找到我有兴趣重命名的文件的 Power shell 片段:

gci -recurse | 其中 {$_.Name -match "[^\u0020-\u007E]"}

未回答的类似 python 问题 - /sf/ask/1250903881/

Rik*_*Rik 2

我在 Stack Overflow上发现了类似的主题。

\n\n

使用以下代码,大多数字符将被转换为它们的“最接近的字符”。虽然我没能得到翻译\xe2\x80\x99。(也许确实如此,我无法在提示中使用它创建文件名;)\xc3\x9f也不会被翻译。

\n\n
function Remove-Diacritics {\nparam ([String]$src = [String]::Empty)\n  $normalized = $src.Normalize( [Text.NormalizationForm]::FormD )\n  $sb = new-object Text.StringBuilder\n  $normalized.ToCharArray() | % {\n    if( [Globalization.CharUnicodeInfo]::GetUnicodeCategory($_) -ne [Globalization.UnicodeCategory]::NonSpacingMark) {\n      [void]$sb.Append($_)\n    }\n  }\n  $sb.ToString()\n}\n\n$files = gci -recurse | where {$_.Name -match "[^\\u0020-\\u007F]"}\n$files | ForEach-Object {\n  $newname = Remove-Diacritics $_.Name\n  if ($_.Name -ne $newname) {\n    $num=1\n    $nextname = $_.Fullname.replace($_.Name,$newname)\n    while(Test-Path -Path $nextname)\n    {\n      $next = ([io.fileinfo]$newname).basename + " ($num)" + ([io.fileinfo]$newname).Extension\n      $nextname = $_.Fullname.replace($_.Name,$next)\n      $num+=1\n    }\n    echo $nextname\n    ren $_.Fullname $nextname\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑:

\n\n

我添加了一些代码来检查文件名是否已存在并添加(1)(2)...如果存在。(它不够聪明,无法检测要(1)重命名的文件名中已存在的内容,因此在这种情况下您会得到(1) (1)。但一如既往......一切都是可编程的;)

\n\n

编辑2

\n\n

这是今晚的最后一篇……

\n\n

这个有不同的替换字符的功能。还添加了一行来更改未知字符,例如\xc3\x9f和。\xe2\x94\xa4_

\n\n
function Convert-ToLatinCharacters {\nparam([string]$inputString)\n  [Text.Encoding]::ASCII.GetString([Text.Encoding]::GetEncoding("Cyrillic").GetBytes($inputString))\n}\n\n$files = gci -recurse | where {$_.Name -match "[^\\u0020-\\u007F]"}\n$files | ForEach-Object {\n  $newname = Convert-ToLatinCharacters $_.Name\n  $newname = $newname.replace(\'?\',\'_\')\n  if ($_.Name -ne $newname) {\n    $num=1\n    $nextname = $_.Fullname.replace($_.Name,$newname)\n    while(Test-Path -Path $nextname)\n    {\n      $next = ([io.fileinfo]$newname).basename + " ($num)" + ([io.fileinfo]$newname).Extension\n      $nextname = $_.Fullname.replace($_.Name,$next)\n      $num+=1\n    }\n    echo $nextname\n    ren $_.Fullname $nextname\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

  • “ß 也不会被翻译。”可能是因为 eszett 应该映射到“ss”,这是*两个*字符。(好吧,如果您不尝试使用 1337-speak,那么要么是“B”,要么是愚蠢的。)显然没有内置映射,因此您必须单独处理它。 (2认同)