1

I am trying to use PS to rename a bunch files within a big share and one of the requirements is to remove a dot from the file name. I have tested a few things with my rather basic skills and of course the most basic of scripts zap the file extension.
I finally came up with something like this:

gci *.xlsx | rename-item -newname {$_.Name.replace(".","") + $_.extension }

But that adds the extension to the end of the filename (while keeping the file extension intact)

I thought I could zap the last four symbols using something like this:

gci *.xlsx | rename-item -newname { $_.basename.substring(0,$_.basename.length-4) + $_.extension }

Overall this seems like an overly complicated operation which could also mess up files without dots (unless I specify xlsx as only 4 symbols to be removed)

Would anyone be able to point me in the right direction to an easier solution? ;-)

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
Lord Jabol
  • 37
  • 6
  • 1
    Is it the first dot? The last dot? All dots? Please provide an example file name or two :) – Mathias R. Jessen May 11 '22 at 10:44
  • 1
    take a look at the `.BaseName` property instead of the `.Name` prop. [*grin*] ///// also, PLEASE add 2 or 3 sample file names & the desired result for each to your Question. – Lee_Dailey May 11 '22 at 11:06
  • It is actually the first dot only that I want to remove so "this_file.looks_like-this.xlsx" There are hundreds of files in various subfolders that I want to catch all at once. – Lord Jabol May 11 '22 at 12:47
  • So you want `$_.BaseName.Remove($_.BaseName.IndexOf('.'), 1) + $_.Extension` :) – Mathias R. Jessen May 11 '22 at 13:25

1 Answers1

1

You were on the right track with your second attempt: using the .BaseName and .Extension properties of the [System.IO.FileInfo] instances[1] output by Get-ChildItem allows you to modify the base name (the file name without its extension) separately, and then re-append the extension to form the full file name:

Get-ChildItem *.xlsx | 
  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.

The above uses the regex-based -replace operator to remove all . instances from the base name; because . is a regex metacharacter (representing any single character), it must be escaped as \. in order to be used literally.
In this simple case, you could have used the [string] type's .Replace() method as well ($_.BaseName.Replace('.', '')), but -replace offers more features and has fewer surprises - see this answer for more information.

Case in point: Say you wanted to remove only the first . from the base name; -replace allows you to do that as follows (but you couldn't do it with .Replace()):

'foo.bar.baz' -replace '\.(.*)$', '$1' # -> 'foobar.baz'

[1] .BaseName isn't a native property of this type; instead, it is a property that PowerShell decorates instances of the type with, using its ETS (Extended Type System).

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    Cheers, you are a gentleman and a wizard! Added -recurse to catch all subfolders for the end result being:(in case anyone needs it in the future) "Get-ChildItem -Recurse *.xlsx | Rename-Item -NewName { ($_.BaseName -replace '\.') + $_.Extension }" – Lord Jabol May 11 '22 at 13:46