$file.Name -ireplace (".", "")
invariably returns an empty string, because the -replace
operator (-ireplace
is just an alias[1]) operates on regexes (regular expressions), in which metacharacter .
matches any character[2].
Since -replace
always replaces all matches it finds, all characters in the input are replaced with the empty string, yielding an empty string overall, and passing an empty string via $newName
to the (positionally implied) -NewName
parameter of Rename-Item
predictably causes the error message you saw.
To match a .
character verbatim in a regex, you must escape it as \.
:
$file.Name -replace '\.', '' # Note: no (...) needed; `, ''` optional
Note that it's generally better to use '...'
quoting rather than "..."
for regexes and string literals meant to be used verbatim.
However:
This would also remove the .
char. in the filename extension, which is undesired.
Also, your command can be streamlined and simplified, as the solution below shows.
A concise, single-pipeline solution:
Get-ChildItem -File -Path "C:\XXXX\XXXX\XXXX" -Recurse -Include *.*.* |
Rename-Item -NewName { ($_.BaseName -replace '\.') + $_.Extension } -WhatIf
Note: The -WhatIf
common parameter in the command above previews the operation. Remove -WhatIf
once you're sure the operation will do what you want.
-File
limits matching to files (not also directories).
-Include *.*.*
limits matching to file names that contain at least 2 .
chars.
Piping the files to rename directly from Get-ChildItem
to Rename-Item
allows you to specify the -NewName
argument as a delay-bind script block ({ ... }
), which can dynamically derive the new name from the name of the respective input file, using the properties of the System.IO.FileInfo instances received from Get-ChildItem
.
$_.BaseName -replace '\.'
removes all literal .
chars. (escaped as \.
in the context of the regex (regular expression) that the -replace
operator operates on) from the file base name (the part without the (last) filename extension).
- Note: not specifying a replacement operand is the same as specifying
''
, the empty string, resulting in the effective removal of the matched string; in other words: ... -replace '\.'
is the same as ... -replace '\.', ''
+ $_.Extension
appends the original extension to the modified base name.
[1] -replace
is case-insensitive by default, as all PowerShell operators are; -ireplace
just makes that fact explicit; there's also the -creplace
variant, where the c
indicates that the operation is case-sensitive.
[2] in single-line strings; in multi-line strings, .
by default doesn't match \n
(newlines), though this can be changed via inline matching option (?s)
at the start of the regex.