[英]How do I remove periods from file names using 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
}
}
关于字符串替换的一件事:当我在没有转义句点的情况下尝试您的示例时,它没有替换任何内容并且没有返回任何内容(空字符串),我相信这回答了您的“无法将参数绑定到参数 '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
开关来过滤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
}
}
$file.Name -ireplace (".", "")
总是返回一个空字符串,因为-replace
运算符( -ireplace
只是一个别名[1] )对正则表达式(正则表达式)进行操作,其中元字符.
匹配任何字符[2] 。
由于-replace
总是替换它找到的所有匹配项,因此输入中的所有字符都被替换为空字符串,从而产生一个整体的空字符串,并通过$newName
将空字符串传递给Rename-Item
的(位置隐含的) -NewName
参数导致您看到的错误消息。
为了匹配一个.
正则表达式中的逐字字符,您必须将其转义为\\.
:
$file.Name -replace '\.', '' # Note: no (...) needed; `, ''` optional
请注意,对于要逐字使用的正则表达式和字符串文字,通常最好使用'...'
引用而不是"..."
。
然而:
这也将删除.
字符。 在文件扩展名中,这是不受欢迎的。
此外,您的命令可以精简和简化,如下面的解决方案所示。
简洁的单管道解决方案:
Get-ChildItem -File -Path "C:\XXXX\XXXX\XXXX" -Recurse -Include *.*.* |
Rename-Item -NewName { ($_.BaseName -replace '\.') + $_.Extension } -WhatIf
注意:上面命令中的-WhatIf
常用参数预览操作。 一旦您确定操作会执行您想要的操作,请删除-WhatIf
。
-File
限制匹配文件(不是目录)。
-Include *.*.*
限制匹配至少包含2 的文件名.
字符。
通过管道将文件直接从Get-ChildItem
Rename-Item
为Rename-Item
允许您将-NewName
参数指定为延迟绑定脚本块( { ... }
),它可以从相应的名称动态派生新名称输入文件,使用从Get-ChildItem
接收的System.IO.FileInfo实例的属性。
$_.BaseName -replace '\\.'
删除所有文字.
字符。 (在-replace
运算符所操作的正则表达式(正则表达式)的上下文中转义为\\.
)来自文件基本名称(没有(最后一个)文件扩展名的部分)。
''
,空字符串,导致匹配字符串被有效去除; 换句话说: ... -replace '\\.'
等同于... -replace '\\.', ''
+ $_.Extension
将原始扩展名附加到修改后的基本名称。
[1] -replace
默认不区分大小写,所有 PowerShell 操作符都是; -ireplace
只是明确说明了这一事实; 还有-creplace
变体,其中c
表示操作区分大小写。
[2] 在单行字符串中; 在多行字符串中, .
默认情况下不匹配\\n
(换行符),尽管这可以通过正则表达式开头的内联匹配选项(?s)
进行更改。
这是另一个利用 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 }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.