Powershell的.Extension
方法似乎不识别双扩展。结果,类似这样的东西:
Get-ChildItem -Path:. | Rename-Item -NewName {
'{0}{1}' -f ($_.BaseName -replace '.', '_'), $_.Extension
}
最终将file.1.tar.gz
重命名为file_1_tar.gz
,而我想要file_1.tar.gz
。
只是疏忽?还是可以减轻?
这是预期的行为。
这是微软文档的一句话。关于[System.IO.Path]::GetExtension
方法,它似乎与其他类似的函数和Powershell Cmdlet共享相同的实现逻辑。
此方法通过在路径中搜索句点(.(,从路径中的最后一个字符开始并继续朝向第一个字符。如果在DirectorySeparatorChar或AltDirectorySepartmentChar字符返回的字符串包含句点及其后面的字符;否则返回String.Empty。
您当然可以通过为tar.gz创建一个异常来缓解这种情况,也可以通过使用字典来定义应该被视为双重异常的其他双重扩展。以下是缓解措施的一个例子。
Get-ChildItem -Path 'C:temp' | % {
$BaseName = $_.BaseName
$Extension = $_.Extension
if ($_.FullName.EndsWith('.tar.gz')) {
$BaseName = $_.BaseName.SubString(0,$_.BaseName.Length -4)
# I used the full name as reference to preserve the case on the filenames
$Extension = $_.FullName.Substring($_.FullName.Length - 7)
}
Rename-Item -Path $_.FullName -NewName (
'{0}{1}' -f ($BaseName -replace '.', '_'), $Extension
)
}
请注意,由于我只有.tar.gz
,我实际上并没有使用字典,但如果您有多个双扩展类型,最好的方法是通过对每个扩展的循环来应用此方法,看看它是否匹配。
举个例子,它循环通过一个数组来检查多个双重扩展
# Outside of the main loop to avoid redeclaring each time.
$DoubleExtensionDict = @('.tar.gz', '.abc.def')
Get-ChildItem -Path 'C:temp' | % {
$BaseName = $_.BaseName
$Extension = $_.Extension
Foreach ($ext in $DoubleExtensionDict) {
if ($_.FullName.EndsWith($ext)) {
$FirstExtLength = ($ext.split('.')[1]).Length
$BaseName = $_.BaseName.SubString(0, $_.BaseName.Length - $FirstExtLength -1)
$Extension = $_.FullName.Substring($_.FullName.Length - 7)
break
}
}
Rename-Item -Path $_.FullName -NewName (
'{0}{1}' -f ($BaseName -replace '.', '_'), $Extension
)
}
参考
Path.GetExtension方法
正如Sage Pourre有用的回答所指出的,在设计中,只有最后一个.
分隔的令牌被视为文件扩展名。
除了创建已知";"多扩展";,正如Sage提出的那样-必须预测所有-您可以根据以下规则尝试启发式(因为您需要排除将.1
作为多重扩展的一部分(:
- 在文件名的结尾,任何不以数字开头的
.
分隔标记的非空运行都被视为多扩展名,包括.
字符:
@{ Name = 'file.1.tar.gz'},
@{ Name = 'file.1.tar.zip'},
@{ Name = 'file.1.html'},
@{ Name = 'file.1.ps1'},
@{ Name = 'other.1'} |
ForEach-Object {
if ($_.Name -match '(.+?)((?:.[^d]+))$') {
$basename = $Matches[1]
$exts = $Matches[2]
} else {
$basename = $_.Name
$exts = ''
}
($basename -replace '.', '_') + $exts
}
以上收益率:
file_1.tar.gz
file_1.tar.zip
file_1.html
file_1.ps1
other_1