This is the intended behavior.
Here's a quote from Microsoft Doc. regarding the [System.IO.Path]::GetExtension method, which seems to share the same implementation logic with other similar functions and Powershell Cmdlets.
This method obtains the extension of path by searching path for a
period (.), starting with the last character in path and continuing
toward the first character. If a period is found before a
DirectorySeparatorChar or AltDirectorySeparatorChar character, the
returned string contains the period and the characters after it;
otherwise, String.Empty is returned.
You can of course mitigate this by either creating an exception for tar.gz and other double extension by using a dictionary to define what should be treated as double exception. Here is an example of mitigation.
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
)
}
Note that since I had only .tar.gz, I did not actually use a dictionary but should you have multiple double extension type, the best way would be to apply this method through a loop against each extension to see if it match.
Take this, for instance, which loop through an array to check against multiple double extensions
# 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
)
}
References
Path.GetExtension Method