如何使用PowerShell从文件名中删除句点



我正试图在PowerShell中编写一个脚本,该脚本在文件夹中搜索包含不必要句点的文件,然后从文件名中批量删除句点。

前任。Example.File.doc--->ExampleFile.doc

每当我运行代码时,控制台都会返回以下信息:"重命名项目:无法将参数绑定到参数'NewName',因为它是一个空字符串。">

有人知道问题出在哪里吗?

提前感谢您的帮助!

$files = get-childitem -path "C:XXXXXXXXXXXX" -Recurse 
foreach($file in $files) {
if($file.Name -match ".") {
$newName = $file.Name -ireplace (".", "")
Rename-Item $file.FullName $newName
Write-Host "Renamed" $file.Name "to $newName at Location:" $file.FullName
}
}

字符串替换有一点:当我在不转义句点的情况下尝试您的示例时,它没有替换任何内容,也没有返回任何内容(空字符串),我相信这回答了您的"无法将参数绑定到参数'NewName',因为它是空字符串">

这是通过逃离这一时期而起作用的。此外,它可以使用或不使用括号。

$string = "the.file.name"
$newstring = $string -ireplace ".", ""
// output: thefilename
$newstring.length
// output: 11
$othernewstring = $string -ireplace (".", "")
// output: thefilename
$othernewstring.length
// output: 11
// What the OP tried
$donothingstring = $string -ireplace (".", "")
// output:
$donothingstring.length
// output: 0

这里有一些关于字符串替换的附加信息,仅供参考https://vexx32.github.io/2019/03/20/PowerShell-Replace-Operator/

$file.Name -ireplace (".", "")

总是返回一个空字符串,因为-replace运算符(-ireplace只是一个别名[1])对正则表达式进行运算,其中元字符.任何字符[2]匹配。

由于-replace总是替换它找到的所有匹配项,因此输入中的所有字符都被空字符串替换,从而产生一个空字符串,并且通过$newName将空字符串传递给Rename-Item的(位置隐含的)-NewName参数会不出所料地导致您看到的错误消息。

在正则表达式中逐字匹配.字符,必须将其转义为.

$file.Name -replace '.', '' # Note: no (...) needed; `, ''` optional

请注意,对于要逐字使用的正则表达式和字符串文字,通常最好使用'...'引用,而不是"..."

但是:

  • 这也将删除.字符。文件名扩展名中,这是不需要的。

  • 此外,您的命令可以简化和精简,如下面的解决方案所示。


简洁的单管道解决方案

Get-ChildItem -File -Path "C:XXXXXXXXXXXX" -Recurse -Include *.*.* | 
Rename-Item -NewName { ($_.BaseName -replace '.') + $_.Extension } -WhatIf

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

  • -File限制与文件的匹配(不包括目录)。

  • -Include *.*.*将匹配限制为至少包含2.个字符的文件名。

  • 通过将要重命名的文件从Get-ChildItem直接管道化为Rename-Item,可以将-NewName参数指定为延迟绑定脚本块({ ... }),该块可以使用从Get-ChildItem接收的System.IO.FileInfo实例的属性,从相应输入文件的名称动态派生新名称。

  • $_.BaseName -replace '.'删除所有文字.字符。(在-replace运算符操作的正则表达式的上下文中转义为.)。

    • 注意:不指定替换操作数与指定空字符串''相同,导致匹配字符串被有效移除;换句话说:... -replace '.'... -replace '.', ''相同
  • + $_.Extension将原始扩展名附加到修改后的基本名称上。


[1]-replace默认情况下不区分大小写,与所有PowerShell操作员一样;-ireplace只是明确了这一事实;还有-creplace变体,其中c表示操作区分大小写

[2]在单行字符串中;在多行字符串中,默认情况下.n(换行符)不匹配,尽管这可以通过正则表达式开头的内联匹配选项(?s)进行更改

这里还有一些其他问题。您应该通过包含-File开关来筛选Get-ChildItem结果以仅返回文件。

您当前的脚本将替换上一个脚本。在文件的扩展名之前,这将导致一些问题。您需要使用$File.BaseName$File.Extension属性来解决此问题。

.replace()方法替换-ireplace

最后,您需要在If语句中使用-like条件。-match条件用于正则表达式,在此处无法正常工作。

$files = get-childitem -Recurse -File 
foreach($file in $files) {
if($file.BaseName -like "*.*") {
$newName = $file.BaseName.Replace(".","") + $file.Extension
Rename-Item $file.FullName $newName
Write-Host "Renamed" $file.Name "to $newName at Location:" $file.FullName
}
}

这里有另一个利用PowerShell管道的解决方案(在测试了将重命名的文件后删除-WhatIf)。

它还使用前瞻性正则表达式来替换文件名中除最后一个点之外的所有点。

Get-ChildItem -Recurse  `
<# Only select files that have more than one '.' in their name #> `
| Where-Object { ($_.Name.ToCharArray() | Where-Object {$_ -eq '.'} | Measure-Object ).Count -gt 1 } `
`
<# Change the location to the directory and rename so you don't have deal with the directory name #> `
<# Also, use a lookahead regex to replace all but the last dot. #> `
| ForEach-Object { Push-Location $_.Directory; Rename-Item $_ ($_.Name -replace ".(?=.*?.)", "") -Verbose -WhatIf; Pop-Location }

以下是使用别名的相同命令的更简洁版本:

dir -r | ?{ ($_.Name.ToCharArray() | ?{ $_ -eq '.' } | measure ).Count -gt 1 } | %{ pushd $_.Directory; ren $_ ($_.Name -replace ".(?=.*?.)", "") -v -wh; popd }

最新更新