如果字符 ASCII 编码大于 128,如何使用字符“_”替换文件夹中的所有文件 NAME 使用 powershell

How to replace all files NAME in A folder with character "_" if the character ASCII encoding is greater than 128 use powershell

示例文件名为 PO 2171 克雷斯科 REVISED.pdf ..... 其中很多文件,文件名不规范,space位置也不固定。 中间space是大于128的字符ASCII码,我想把大于128的字符ASCII码一次性替换成“_”

我还没学过Powershell。 非常感谢。

为此你需要正则表达式。

下面我使用 ASCII 范围 32 - 129(十六进制 \x20-\x81)来替换任何控制字符:

(Get-ChildItem -Path 'X:\TheFolderWhereTheFilesAre' -File) | 
    Where-Object { $_.Name -match '[^\x20-\x81]' } | 
    Rename-Item -NewName { $_.Name -replace '[^\x20-\x81]+', '_' }

正则表达式详细信息:

[^\x20-\x81]     Match a single character NOT in the range between ASCII character 0x20 (32 decimal) and ASCII character 0x81 (129 decimal)
   +             Between one and unlimited times, as many times as possible, giving back as needed (greedy)

is effective, but there's a simpler, more direct solution, using the .NET regex Unicode code block \p{IsBasicLatin}, which directly matches any ASCII-range Unicode character (all .NET strings are Unicode strings, internally composed of UTF-16 个代码单元)。

否定,\P{IsBasicLatin}(注意大写P),匹配ASCII之外的任何字符范围,以便您可以在 regex-based -replace 运算符的帮助下使用以下内容将所有 non-ASCII-range 字符替换为 _

(Get-ChildItem -File) |  # Get all files in the current dir.
  Rename-Item -NewName { $_.Name -replace '\P{IsBasicLatin', '_' } -WhatIf

注意:上面命令中的-WhatIf common parameter预览操作。一旦您确定该操作将执行您想要的操作,请删除 -WhatIf

注:

  • (...) 中包含 Get-ChildItem 调用可确保在执行重命名之前 首先 收集所有匹配的文件。这可以防止 already-renamed 文件 re-entering 文件枚举可能引起的问题。

  • 因为只有 文件 (-File) 需要重命名,所以您不必担心 包含non-ASCII-range 个字符:Rename-Item 安静地忽略将文件重命名为已有名称的尝试。

    • 不幸的是,对于 目录 ,这 不是 正确,这样的尝试会导致错误;这个不幸的差异在 PowerShell 7.2.4 中出现,是 GitHub issue #14903.
    • 的主题
  • 严格来说,.NET 字符 ([char] (System.Char) instances) are 16-bit Unicode code units (UTF-16), which can individually only represent a complete Unicode character in the so-called BMP (Basic Multilingual Plane),即 code-point 范围 0x0-0xFFFF。超出该范围的 Unicode 字符,特别是 emoji,如 ,需要用 two .NET [char] 实例,so-called 代理对表示。因此,上述解决方案替换了此类字符两个 _ 个字符,如下例所示:

      PS> 'A !' -replace '\P{IsBasicLatin}', '_'
    
      A __!        # !! *two* '_' chars.