首页 > 解决方案 > 在cmd/batch中逐个字符循环字符串?

问题描述

我希望摆脱特定目录中文件夹名称中的所有特殊字符。

我在想我可以将每个字符转换成它的 ASCII 字符值,如果它不在“正常”字符的范围内,我会替换它。

我找不到任何东西可以告诉我如何遍历字符串中的每个字符。

for /d %%i in (C:\temp\*) do (
    echo before %%~ni
    for CHAR in %%~ni do (
        if CHAR < 33 || CHAR > 126 (
            CHAR = 95
        )
    )
    echo after %%~ni
)
echo Ende

标签: batch-filecmd

解决方案


我决定提供一个使用 PowerShell 2.0 的批处理文件版本(使其与 Windows 7 系统兼容)。它通过使用十六进制字符而不是您在问题中提到的十进制字符来工作,ASCII 33 = Hex 21,ASCII 126 = Hex 7E,我将其替换为下划线字符 , _,如您的示例所示:

批处理文件

@PowerShell -NoP "GCI 'C:\temp'|"^
 "?{$_.PSIsContainer -And $_.BaseName -Match '[^\x21-\x7E]+'}|"^
 "%%{RnI $_.FullName ($_.BaseName -Replace '[^\x21-\x7E]+', '_') -Wh}"
@Pause

上面使用-WhatIf, (缩写为-Wh来向您展示如果不实际执行会发生什么。如果您对输出感到满意,您可以删除 -Wh最后一行@Pause.

当然,您可能会忘记从批处理文件中运行它并直接作为PowerShell 脚本执行此操作,(未缩短以帮助您了解正在发生的事情)

Get-ChildItem 'C:\temp' |
    Where-Object {
        $_.PSIsContainer -And $_.BaseName -Match '[^\x21-\x7E]+'
    } | ForEach-Object {
        Rename-Item -Path $_.FullName -NewName ($_.BaseName -Replace '[^\x21-\x7E]+', '_')
    }

与批处理文件示例不同,我没有包含该-WhatIf语句,因此请注意运行它会重命名目录


注意

这些解决方案不考虑任何现有目录已经包含您希望重命名的名称。如果可能存在这种情况,您将需要改进我发布的内容。


[编辑 /]

如果您只想查看现有和替换格式的目录名称,而不是实际进行任何重命名,那么您可能更喜欢不同的布局。

这个只是以不同的颜色将它们显示在另一个之上:

@PowerShell -NoP "GCI 'C:\temp\test'|"^
 "?{$_.PSIsContainer -And $_.BaseName -Match '[^\x21-\x7E]+'}|"^
      "%%{Write-Host($_.BaseName)-F Red;Write-Host($_.BaseName -Replace '[^\x21-\x7E]+', '_')-F Cyan}"
@Pause

和 .ps1 版本:

Get-ChildItem 'C:\temp\test' |
    Where-Object {
        $_.PSIsContainer -And $_.BaseName -Match '[^\x21-\x7E]+'
    } | ForEach-Object {
        Write-Host $_.BaseName -ForegroundColor Red
        Write-Host ($_.BaseName -Replace '[^\x21-\x7E]+', '_') -ForegroundColor Cyan
    }

推荐阅读