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

时间:2019-12-13 22:59:33

标签: powershell

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

例如Example.File.doc ---> ExampleFile.doc

每当我运行代码时,控制台都会返回以下内容:“ Rename-Item:由于参数为空字符串,因此无法将其绑定到参数'NewName'。”

有人知道这个问题是什么吗?

在此先感谢您的帮助!

$files = get-childitem -path "C:\XXXX\XXXX\XXXX" -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
    }
}

4 个答案:

答案 0 :(得分:2)

关于字符串替换的一件事:当我尝试在示例中使用转义符时,它没有替换任何内容且未返回任何内容(空字符串),我相信这可以回答您的“无法将参数绑定到参数'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/

答案 1 :(得分:1)

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

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

使用-ireplace方法替换.replace()

最后,您需要在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
    }
}

答案 2 :(得分:1)

  

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

始终返回空字符串 ,因为-replace operator-ireplace只是别名 [1] )对regexes(正则表达式)进行操作,其中元字符 .任何字符 [2] 匹配。

由于-replace始终替换找到的 all 匹配项,因此输入中的所有字符均替换为空字符串,整体上产生空字符串,并通过{{1 }}到$newName的{​​{1}}参数(在位置上隐含)会导致您看到错误消息。

在正则表达式中匹配-NewName字符 verbatim ,您必须将其转义为Rename-Item :< / p>

.

请注意,对于要逐字使用的正则表达式和字符串文字,通常最好使用\.引号而不是$file.Name -replace '\.', '' # Note: no (...) needed; `, ''` optional

但是:

  • 这还将删除'...'字符。在文件名扩展名 中,这是不希望的。

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


一种简洁的单管道解决方案

"..."

注意:上方命令中的-WhatIf common parameter会预览该操作。确定操作将执行您想要的操作后,请删除.

  • Get-ChildItem -File -Path "C:\XXXX\XXXX\XXXX" -Recurse -Include *.*.* | Rename-Item -NewName { ($_.BaseName -replace '\.') + $_.Extension } -WhatIf 限制了与文件(而不是目录)匹配。

  • -WhatIf将匹配项限制为至少包含 2 -File个字符的文件名。

  • 通过将文件直接从-Include *.*.*重命名为.,可以将Get-ChildItem自变量指定为delay-bind script blockRename-Item),可以使用从-NewName接收到的System.IO.FileInfo实例的属性,从相应输入文件的名称中动态得出新名称。

  • { ... }删除所有文字Get-ChildItem字符。 (从{em> base 文件名开始,(在regex操作的-replace operator(正则表达式)的上下文中转义为$_.BaseName -replace '\.')(没有(最后)文件名扩展名)。

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


默认情况下,

[1] ... -replace '\.', ''不区分大小写 ,因为所有PowerShell运算符都是; + $_.Extension只是表明了这一事实;还有一个-replace变体,其中-ireplace表示该操作区分大小写

单行字符串中的

[2];在多行字符串中,默认情况下-creplacec(换行符)不匹配,尽管可以在开始时通过内联匹配选项.进行更改正则表达式。

答案 3 :(得分:0)

这是利用PowerShell管道的另一种解决方案(在测试了要重命名的文件后,删除-WhatIf

它还使用lookahead regular expression替换文件名中除最后一个点外的所有点。

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 }