1

I am trying to rename files in multiple folder with same name structure. I got the following files:

  • (1).txt
  • (2).txt
  • (3).txt

I want to add the following text in front of it: "Subject is missing"

I only want to rename these files all other should remain the same

mklement0
  • 382,024
  • 64
  • 607
  • 775
Nick
  • 161
  • 1
  • 2
  • 14

1 Answers1

1

Tip of the hat to LotPings for suggesting the use of a look-ahead assertion in the regex.

Get-ChildItem -File | Rename-Item -NewName { 
  $_.Name -replace '^(?=\(\d+\)\.)', 'Subject is missing '
} -WhatIf

-WhatIf previews the renaming operation; remove it to perform actual renaming.

  • Get-ChildItem -File enumerates files only, but without a name filter - while you could try to apply a wildcard-based filter up front - e.g., -Filter '([0-9]).*' - you couldn't ensure that multi-digit names (e.g., (13).txt) are properly matched.

    • You can, however, pre-filter the results, with -Filter '(*).*'
  • The Rename-Item call uses a delay-bind script block to derive the new name.

    • It takes advantage of the fact that (a) -rename returns the input string unmodified if the regex doesn't match, (b) Rename-Item does nothing if the new filename is the same as the old.
  • In the regex passed to -replace, the positive look-ahead assertion (?=...) (which is matched at the start of the input string (^)) looks for a match for subexpression \(\d+\)\. without considering what it matches a part of what should be replaced. In effect, only the start position (^) of an input string is matched and "replaced".

    • Subexpression \(\d+\)\. matches a literal ( (escaped as \(), followed by 1 or more (+) digits (\d), followed by a literal ) and a literal . (\.), which marks the start of the filename extension. (Replace .\ with $, the end-of-input assertion if you want to match filenames that have no extension).
  • Therefore, replacement operand 'Subject is missing ' is effectively prepended to the input string so that, e.g., (1).txt returns Subject is missing (1).txt.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    As an alternative with a [positive lookahead](https://www.regular-expressions.info/lookaround.html) just the anchor `^` could be replaced with the text to prepend: `$_.Name -replace '^(?=\(\d+\)$)', 'Subject is missing '` –  Mar 03 '19 at 20:45
  • I tried the following Get-ChildItem -File | Rename-Item -NewName { $_.Name -replace '^(?=\(\d+\)$)', 'Subject is missing ' } It did change nothing, the files (1), (2), (3) all remain the same. – Nick Mar 04 '19 at 17:08
  • The is no white space it's just '(1)' and other numbers. But the structure of 1 single files is '(*)' – Nick Mar 04 '19 at 17:26
  • For most of them it worked fine, I got only one error. Rename-Item : Cannot bind argument to parameter 'NewName' because it is an empty string. At line:1 char:114 But I guess that's because that's an empty filename. I fixed that now with some other code. – Nick Mar 04 '19 at 17:38