我正在尝试在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
}
}
答案 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 block(Rename-Item
),可以使用从-NewName
接收到的System.IO.FileInfo实例的属性,从相应输入文件的名称中动态得出新名称。
{ ... }
删除所有文字Get-ChildItem
字符。 (从{em> base 文件名开始,(在regex操作的-replace
operator(正则表达式)的上下文中转义为$_.BaseName -replace '\.'
)(没有(最后)文件名扩展名)。
.
(空字符串)相同,导致有效删除了匹配的字符串;换句话说:\.
与''
... -replace '\.'
将原始扩展名附加到修改后的基本名称上。
[1] ... -replace '\.', ''
不区分大小写 ,因为所有PowerShell运算符都是; + $_.Extension
只是表明了这一事实;还有一个-replace
变体,其中-ireplace
表示该操作区分大小写 。
[2];在多行字符串中,默认情况下-creplace
与c
(换行符)不匹配,尽管可以在开始时通过内联匹配选项.
进行更改正则表达式。
答案 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 }