【问题标题】:Remove some characters from filename using powershell使用powershell从文件名中删除一些字符
【发布时间】:2014-09-14 21:58:33
【问题描述】:

我有 100 个文件,例如命名为:(不带引号)

管理和改进自己的学习 [L3] {CBA849}”和

"记笔记和做笔记 [L3] {CBA851}"

我想重命名它,使其仅显示“CBA849”和“CBA851”并删除其他任何内容。

换句话说,我想将文件代码保留在 {....} 大括号内。

有什么方法可以实现吗? (注意:不是替换字符)

谢谢

【问题讨论】:

    标签: file powershell rename


    【解决方案1】:
    Rename-Item -LiteralPath $path ([regex]::match($path, '{(.+)}')).Groups[1].Value
    
    • 您需要 -LiteralPath,因为文件名包含括号。
    • [regex]::match($path, '{(.+)}') 匹配大括号及其内容,并将内容捕获到匹配组中。 .Groups[1].Value 返回第一个(在本例中是唯一的)匹配组的值。
    • 这假定所有文件都以问题中显示的格式命名。如果名称中的其他地方可能存在花括号,请将正则表达式 {(.+)} 更改为 {(.+?)}$

    【讨论】:

    • TheMadTechnician 提出了一个很好的问题:这些是完整的文件名吗,您是否希望完整的文件名是大括号之间的部分,没有扩展名,或者您是否将扩展名排除在描述之外因为您假设在重命名文件时它们会被保留?如果有 are 扩展,则正则表达式匹配需要包含它们。请澄清。
    • 我最终修改了我的以匹配 BaseName,并包含 Extension 属性以保留文件上的任何扩展名。不确定这将如何与您的答案一起使用,但需要考虑。
    • @TheMadTechnician 为了保留扩展名(如果有),我将 + (Get-Item -LiteralPath $path).Extension 添加到 NewName 参数中。暂时不编辑答案,因为直到我们在这一点上从 OP 到这里,我也会假设“删除其他任何内容”意味着删除其他任何内容。 ;)
    • 嗨,伙计们,如果我让你感到困惑,对不起。我的问题是我有 100 个这样命名的文件:file1:“管理和改进自己的学习 [L3] {CBA849}”和 File2:“Note-taking and Note-making [L3] {CBA851}” File3: .... .{CBA561}。我对 {} 括号中的内容感兴趣。我希望我的文件将其重命名为“CBA851”.....等等从它中删除所有其他字符串。所以最后我的文件名看起来像 File1:"CBA849.pdf" 和 File2:"CBA851.pdf"........File(n):".......pdf" 希望这个清楚了。谢谢
    • 我的想法是,一旦我将“.docx”转换为“.pdf”,然后我会跑到上面去去除刺痛。
    【解决方案2】:

    我个人会使用正则表达式匹配:

    GCI $path | ?{$_.Name -match "(?:.*?{)(.*?)(?:})(\..*)?$"}|%{$_.MoveTo("$($_.Directory)\$($matches[1])$($matches[2])")}
    

    编辑: 正如 Adi Inbar 所说,我创建了一个过于复杂的 RegEx 模式。正如他所建议的那样简化(尽管仍然允许扩展)是一个修改后的答案:

    GCI $path | ?{$_.BaseName -match "{(.*?)}$"}|%{$_.MoveTo("$($_.Directory)\$($matches[1])$($_.Extension)")}
    

    编辑:好的,这是细分...

    GCI 是 Get-ChildItem 的缩写,它会提取指定目录的列表,但我想您可能已经猜到了。

    然后它通过管道传递到 Where{} 子句(?是 Where 的别名)。它与 GCI 命令提供的文件和文件夹的 BaseName 相匹配。 BaseName 属性实际上是由 PowerShell 生成的,它获取文件的名称、扩展名和所有内容,然后从中删除扩展名(带有前面的句点),所以如果文件名是 Sample.txt 那么它为您提供 Sample 作为 BaseName。

    它与 RegEx(正则表达式的缩写)模式匹配。如果您不知道 RegEx 是什么,请随时查找并阅读它(Google 是您的朋友)。基础是它匹配模式而不是实际文本。在这种情况下,模式是文件名末尾大括号之间的任何内容。

    过去它进入了 ForEach 循环(我为 ForEach 使用了 % 别名)。对于与 RegEx 模式匹配的每个文件,它对该文件执行 MoveTo() 方法。要将其移动到的位置是该文件的当前目录(使用 $.Directory 获取),后跟一个反斜杠,然后是 $Matches[1](我将在一秒钟内了解),然后文件的原始扩展名(使用 $.Extension 获得)。现在您将看到我将目录和扩展名包装在子表达式 $() 中,因为如果您尝试指定变量的属性,则使用字符串外推(如果您将它们放在双引号内,它如何自动神奇地扩展变量)必须把它放在一个子表达式中。否则,它会尝试仅扩展变量本身,并以纯文本形式显示 .Whatever 属性名称。

    最后,$Matches 是一个自动变量,当您使用一些东西进行匹配时会填充它(例如 <something> -match <something else>,就像我们在 Where 子句中所做的那样)。它的第一条记录是匹配<something>的整个字符串,然后下一条记录是基于<something else>的匹配。

    我希望这一切都为您解决。如果您有具体问题,请告诉我。如果此答案解决了您的问题,请将其标记为已接受。

    【讨论】:

    • 关于正则表达式的几点建议: 1. 无需将左大括号前的文本与.*? 匹配。正则表达式不必匹配整个字符串,只需匹配其中的一部分,因此它应该只关注您想要匹配的部分,其余部分不需要通用匹配。 2. 为此目的同时使用匹配组和非捕获组是多余的。您使用的所有匹配组的值与{(.*?)}(?:{)(.*?)(?:}) 完全相同。您也可以使用(?:{).*?(?:}),然后使用整个匹配项 ($matches[0]),但不需要两者。
    • @AdiInbar 感谢您的提醒!我实际上已经完成了多个匹配组,因为(虽然用户没有指定)我允许扩展。我不记得你是否可以在没有非捕获组的情况下做到这一点,所以决定谨慎起见,但我很感激这些提醒。我将按照建议使用较短的 RegEx 更新我的答案。
    • 关于扩展的好问题。我按字面意思回答了这个问题——如果他说他希望文件名只是花括号内的一部分“并删除其他任何内容”,这就是他将要得到的。但是,如果他假设扩展超出范围并假设它们会被保留,那么除非它们包含在匹配中,否则不会发生这种情况。
    • 这段代码对我有用:优秀@TheMadTechnician 你应该被称为 ThePowerTechnician:非常感谢 GCI $path | ?{$_.BaseName -match "{(.*?)}$"}|%{$_.MoveTo("$($_.Directory)\$($matches[1])$($_.Extension )")}。解释一下它的工作原理会很有帮助
    【解决方案3】:
    $f=gi $filepath;
    $f.MoveTo($f.fullname.Replace($f.name,$f.name.substring($f.name.indexof("{")+1,($f.name.indexof("}")-1)-$f.name.indexof("{"))+$f.extension))
    
    1. 使用 get-item (gi) 获取要重命名为 [System.IO.FileInfo] 对象的文件。
    2. 一旦你在 $f 中有文件对象,脚本正在执行:

      • 移至
      • $f.FullName:现有文件的完整路径(C:\some\dir\Test {ABC123}.txt)
      • 通过使用 Replace 函数将旧文件名 ($f.name) 替换为所需名称,将 FullName 修改为新文件名
        • 文件名的子字符串函数将允许您只获取大括号之间的字符串。
          • 在名称字符串中查找 OpenCurlyBracket 的索引
          • 在名称字符串中查找 CloseCurlyBracket 的索引
        • 用 Substring 函数识别大括号之间的文本后,将文件扩展名附加到新文件名

    【讨论】:

    • 小心 MoveTo 方法。如果您不指定完整路径,它会将文件移动到 .NET 工作目录,该目录是 PowerShell 会话开始时的工作目录(通常是用户配置文件目录),因此您所拥有的通常会移动文件到 C:\Users\\CBA849 等。所以如果你想这样做,你需要在路径参数的开头添加"$pwd\" + 。我个人认为最好还是坚持 Rename-ItemMove-Item
    • 谢谢,更新了 $f.FullName 路径以确保文件保留在其原始位置。
    • Powershell 在这里所做的事情可能需要一些详细说明。
    猜你喜欢
    • 2015-05-18
    • 2013-05-03
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 2019-02-18
    相关资源
    最近更新 更多