【发布时间】:2014-09-14 21:58:33
【问题描述】:
我有 100 个文件,例如命名为:(不带引号)
“管理和改进自己的学习 [L3] {CBA849}”和
"记笔记和做笔记 [L3] {CBA851}"
我想重命名它,使其仅显示“CBA849”和“CBA851”并删除其他任何内容。
换句话说,我想将文件代码保留在 {....} 大括号内。
有什么方法可以实现吗? (注意:不是替换字符)
谢谢
【问题讨论】:
标签: file powershell rename
我有 100 个文件,例如命名为:(不带引号)
“管理和改进自己的学习 [L3] {CBA849}”和
"记笔记和做笔记 [L3] {CBA851}"
我想重命名它,使其仅显示“CBA849”和“CBA851”并删除其他任何内容。
换句话说,我想将文件代码保留在 {....} 大括号内。
有什么方法可以实现吗? (注意:不是替换字符)
谢谢
【问题讨论】:
标签: file powershell rename
Rename-Item -LiteralPath $path ([regex]::match($path, '{(.+)}')).Groups[1].Value
[regex]::match($path, '{(.+)}') 匹配大括号及其内容,并将内容捕获到匹配组中。 .Groups[1].Value 返回第一个(在本例中是唯一的)匹配组的值。{(.+)} 更改为 {(.+?)}$。【讨论】:
+ (Get-Item -LiteralPath $path).Extension 添加到 NewName 参数中。暂时不编辑答案,因为直到我们在这一点上从 OP 到这里,我也会假设“删除其他任何内容”意味着删除其他任何内容。 ;)
我个人会使用正则表达式匹配:
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>的匹配。
我希望这一切都为您解决。如果您有具体问题,请告诉我。如果此答案解决了您的问题,请将其标记为已接受。
【讨论】:
.*? 匹配。正则表达式不必匹配整个字符串,只需匹配其中的一部分,因此它应该只关注您想要匹配的部分,其余部分不需要通用匹配。 2. 为此目的同时使用匹配组和非捕获组是多余的。您使用的所有匹配组的值与{(.*?)} 和(?:{)(.*?)(?:}) 完全相同。您也可以使用(?:{).*?(?:}),然后使用整个匹配项 ($matches[0]),但不需要两者。
$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))
一旦你在 $f 中有文件对象,脚本正在执行:
【讨论】:
"$pwd\" + 。我个人认为最好还是坚持 Rename-Item 和 Move-Item。