1

I have a folder that contains files like 'goodthing 2007adsdfff.pdf', 'betterthing 2007adfdsw.pdf', and 'bestthing_2007fdsfad.pdf', I want to be able to rename each, eliminating all text including 2007 OR _2007 to the end of the string keeping .pdf and getting this result: 'goodthing.pdf' 'betterthing.pdf' 'bestthing.pdf' I've tried this with the "_2007", but haven't figured out a conditional to also handle the "2007". Any advice on how to accomplish this is greatly appreciated.

Get-ChildItem 'C:Temp\' -Name -Filter *.pdf | foreach { $_.Split("_2017")[0].substring(0)}
RaabK
  • 23
  • 3
  • 1
    the `-split` operator uses regex, so you could use >>> `($_.BaseName -split ' \d{4}|_\d{4}')[0]` <<< to get the truncated basename. then just add the `.Extension` & path info to it for your filename. – Lee_Dailey Dec 09 '19 at 21:57
  • I like it. This regex is versatile because it works well if there is more than one space in the file name. Something like "best thing 2007asdfda.pdf" as well as "bestthing 2007dfsfds.pdf" gets picked up to output "best thing.pdf" and "bestthing.pdf" Thank you – RaabK Dec 10 '19 at 15:57
  • you are most welcome! glad to help a bit ... [*grin*] – Lee_Dailey Dec 10 '19 at 16:19

2 Answers2

0

Without knowing the names of all the potential files, I can offer this solution that is 100%:

PS> $flist = ("goodthing 2007adsdfff.pdf","betterthing 2007adfdsw.pdf","bestthing_2007fdsfad.pdf")
PS> foreach ($f in $flist) {$nicename = ($f -replace "([\w\s]+)2007.*(\.\w+)", '$1$2') -replace "[\s_].","." ;$nicename}

goodthing.pdf
betterthing.pdf
bestthing.pdf

Two challenges:

  1. the underscore is actually part of the \w character class. So the alternative to the above is to complicate the regex or try to assume that there will always be only one '_' before the 2007. Both seemed risky to me.

  2. if there are spaces in filenames, there is no telling if you might encounter more than one. This solution removes only the one right before 2007.

The magic:

The -replace operator enables you to quickly capture text in () and re-use it in variables like $1$2. If you have more complex captures, you just have to figure out the order they are assigned.

Hope this helps.

adamt8
  • 308
  • 1
  • 7
0

Try the following:

Get-ChildItem 'C:\Temp' -Name -Filter *.pdf |
  Rename-Item -NewName { $_.Name -replace '[_ ][^.]+' } -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 Rename-Item with a delay-bind script block and the -replace operator as follows:

  • Regex [_ ][^.]+ matches everything from the first space or _ char. (character set [ _]) through to the following literal . char. ([^.]+ matches one or more chars. other than (^) than .) - that is, everything from the first / _ through to the filename extension (excluding the .).

    • Note: To guard against file names such as _2017.pdf matching (which would result in just .pdf as the new name), use the following regex instead: '(?<=.)[_ ][^.]+'
  • By not providing a replacement operand to -replace, what is matched is replace with the empty string and therefore effectively removed.

The net effect is that input files named
'goodthing 2007adsdfff.pdf', 'betterthing 2007adfdsw.pdf', 'bestthing_2007fdsfad.pdf'
are renamed to
'goodthing.pdf', 'betterthing.pdf', 'bestthing.pdf'

mklement0
  • 382,024
  • 64
  • 607
  • 775