【问题标题】:Trying to batch remove non visible special characters from filenames尝试从文件名中批量删除不可见的特殊字符
【发布时间】:2019-08-16 19:47:37
【问题描述】:

我有 100 多个由具有隐藏特殊字符的程序创建的文件名。在 Windows 资源管理器中,文件名看起来是正确的,但是将文件名复制并粘贴到诸如 notepad++ 之类的程序中时,两端都带有 ?。即,?文件名?。通过右键单击、删除文件名并重新输入文件名来手动重命名文件名可以解决问题。为了看到多余的字符,我必须将 notepad++ 中的编码从 UTF-8 切换到 ANSI。在帮助下,我确定了尾随的“?”作为 id 65279,或 BOM。 What is this char? 65279 ''

我需要将文件重新加载到程序中,但由于隐藏的特殊字符,程序无法正确读取它们。

有没有办法使用 PowerShell 来清理文件?理想情况下,只有隐藏的特殊字符被删除,文件名的其余部分(包括下划线)保持不变。文件名冲突在当前情况下应该不是问题,但如果出现异常,自动覆盖将是一个很好的解决方案。输出文件名由包含以下内容的 java 脚本生成:

var objName = f[myCounter].contents.replace(/ /g,"_").toLowerCase();
app.pngExportPreferences.pageString = curPage.name;
var myFilePath = myDoc.filePath + "/" + objName + ".png"; //export to a folder of the current document
var myFile = new File(myFilePath);
myDoc.exportFile(ExportFormat.PNG_FORMAT, myFile, false);

如果问题在那里更容易解决。我对 PowerShell 和 javascript 非常陌生。

我尝试了一些我发现的 PowerShell 脚本,包括:

dir -Recurse | ?{$_.Name -match $re}  | %{ren -literalpath $_.FullName -newname (join-path (get-item $_.PSPArentPath) $($_.Name -replace $re,""))}

gci *.png | Rename-Item -NewName {$_ -replace '_*(\[.*?\]|\(.*?\))_*' -replace '_+', ' '}

他们没有删除隐藏的特殊字符。

【问题讨论】:

    标签: windows powershell


    【解决方案1】:

    复制有问题的文件名:

    echo hi > ([char]65279 + 'hithere' + [char]65279 + '.txt')
    

    试试这个。如果看起来不错,把rename-item后面的-whatif去掉,这样就真的生效了。

    dir | foreach {
      $name = $_.name
      $chars = [char[]]$name | where { $_ -in [char]' '..[char]'~' } # printable ascii
      $newname = -join $chars   # make a string again
      # $newname = $name -replace '[^ -~]'   # alternative
      if ($newname.length -lt $name.length) { # ascii name is smaller  
        $_ | rename-item -newname $newname -whatif
      }
    }
    

    参考:http://facweb.cs.depaul.edu/sjost/it212/documents/ascii-pr.htm

    【讨论】:

    • 感谢您为此抽出时间。我想它成功了一半。当我在将文件名字符串运行到​​记事本++后粘贴它时,它现在读取为“文件名?”而不是“?文件名?”。为了看到多余的字符,我必须将 n++ 中的编码从 UTF-8 切换到 ANSI。
    • 嗯,你使用的范围是 32..126 吗?如果将奇怪的字符复制并粘贴到 powershell 会发生什么?像[int][char]'ó' 一样给243
    • 是的,我完全按照提供的方式使用它。粘贴到 powershell 中得到与 notepad++ 相同的结果。如果我在有问题的问号上使用 [int][char]'' 它会给出代码 65279。一项小研究表明这是一个 BOM 字符。我现在正在研究更多。 stackoverflow.com/questions/6784799/what-is-this-char-65279
    • 对不起,我误读了您的评论。我现在正在尝试删除 -whatif。它似乎像你描述的那样工作,我现在要对大量文件进行尝试。谢谢!我认为这是解决方案。
    • 确认这在更大范围内有效。再次感谢你。我花了大约 14 个小时试图找出文件没有读入的原因。今天你已经保存了一个工作流程、一个周末,而且很可能是某个键盘免受某些抨击。
    【解决方案2】:

    以下脚本可能会有所帮助。基于Character classes in regular expressions

    在您将有问题的字符识别为U+FEFF 零宽度不间断空格后,

    正则表达式更新'\p{IsGeneralPunctuation}|\ufeff'
    应该适用于大多数文件名,即使是 非 ascii 文件名(参见 Naming Conventions)。

    Get-ChildItem -Recurse -File |
        ForEach-Object {
            $strange = $_.Name
            $string  = $strange -creplace '\p{IsGeneralPunctuation}|\ufeff'
            if ( $strange.Length -ne $string.Length ) {
                'strange {0,3} {1}' -f $strange.Length, $strange
                'string  {0,3} {1}' -f $string.Length,  $string
                $_ | Rename-Item -NewName $string -WhatIf
            }
        }
    

    【讨论】:

    • 感谢您为此抽出时间。它运行良好并且与 u/js2010 具有相同的问题,因为它看起来捕获前导特殊字符而不是尾随特殊字符。当我在将文件名字符串运行到​​记事本++后粘贴它时,它现在读取为“文件名?”而不是“?文件名?”。为了看到多余的字符,我必须将 n++ 中的编码从 UTF-8 切换到 ANSI。
    • 谢谢@JosefZ,我不知道-Whatif 是做什么的,但就像@js2010 的代码一样,如果我从您的脚本中删除-Whatif 语句,它将正确删除两个有问题的字符。如果包含 -Whatif 语句,它只会删除第一个有问题的字符。这段代码生成了一个代表我遇到的问题的文件:echo hi > ([char]65279 + 'hithere' + [char]65279 + '.txt')非常感谢您抽出宝贵的时间!
    • Get-Help about_CommonParameters:除了常用参数外,许多 cmdlet 还提供WhatIfConfirm 风险缓解参数。涉及系统或用户数据风险的 Cmdlet 通常会提供这些参数。_请阅读 ˙Get-Help Rename-Item -online˙Get-Help Rename-Item -Parameter WhatIf:@ 987654331@ 显示 cmdlet 运行时会发生什么。 cmdlet 未运行。
    猜你喜欢
    • 2016-02-04
    • 2015-09-24
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多