3

I'm trying to update a bunch of .jpg images so that they refresh on my website. They're currently stored on my PC like this:

media
+- random-project
|  +- 1.jpg
|  +- 2.jpg
|  +- 3.jpg
|  `- thumb.png
+- another-random-project
|  +- 1.jpg
|  `- thumb.png

I'm trying to batch rename all 1.jpg, 2.jpg etc. to 1a.jpg, 2a.jpg.

I'm thinking using Windows PowerShell and something like

Get-ChildItem -Recurse -Filter "[0-9]+.jpg" | foreach { $_.FullName}

Dir *.jpg | Rename-Item -NewName { $_.Name  -replace "[0-9]+.jpg","[0-9]a.jpg" }

but have never used the program before. What do you think?

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328

3 Answers3

1
  • It's always worth using the -Filter parameter, if available: it performs filtering at the source and is therefore typically much faster than filtering later.

  • The syntax of the (string) value accepted by the -Filter parameter is cmdlet- / PowerShell drive provider-specific.
    In the case of Get-ChildItem (and its built-in aliases dir and, in Windows PowerShell, ls), it accepts a single wildcard expression - similar to, but distinct from PowerShell's own wildcard expressions - whose supported syntax is platform-dependent:

    • On Windows, the expression may only contain * and ? wildcards - see this answer.

    • In PowerShell Core on Unix platforms, the expression may also contain character sets such as [0-9].

[0-9]+.jpg does not work as a -Filter value, because it is a regex (regular expression).

As an aside: You probably meant to use . as a literal, in which case you'd have to escape it in the regex as \., because . is a regex metacharacter representing any char. in the input.

You cannot emulate regular expression [0-9]+.jpg with a wildcard expression, because even when wildcard expressions do support character sets such as [0-9], they lack subexpression duplication symbols (quantifiers) such as + and * and ?.
(By contrast, wildcard metacharacters * / ? are stand-alone constructs that represent any possibly empty sequence of characters / exactly one character).


Note: -WhatIf has been added to the Rename-Item calls below to preview any changes that would be made.
Remove -WhatIf to perform actual renaming.

[PowerShell Core on Unix only] If all *.jpg files of interest have a base name (filename root) that is limited to a single-digit number, (e.g., 1.jpg, ..., 9.jpg), you can get away with passing wildcard expression [0-9].jpg to -Filter:

Get-ChildItem -File -Recurse -Filter [0-9].jpg |
  Rename-Item -NewName { $_.BaseName + 'a' + $_.Extension } -WhatIf

Note how passing script-block argument { $_.BaseName + 'a' + $_.Extension } to parameter -NewName constructs the new filename from the input file's base name, followed by literal a, followed by the input file's extension.


Otherwise,

  • use wildcard expression *.jpg for efficient pre-filtering,

  • then narrow the pre-filtered results down to specific regex-based matches with a Where-Object call that uses -match to compare each input file's base name to regex ^[0-9]+$, i.e., to test if it is only composed of decimal digits.

Note:
* The command below uses PSv3+ Get-ChildItem and Where-Object syntax.
* The regex passed to -match uses single-quoting ('...') rather than double-quoting ("...") to ensure that PowerShell's string interpolation doesn't get in the way.

Get-ChildItem -File -Recurse -Filter *.jpg |
  Where-Object BaseName -match '^[0-9]+$' |
    Rename-Item -NewName { $_.BaseName + 'a' + $_.Extension  } -WhatIf
Community
  • 1
  • 1
mklement0
  • 382,024
  • 64
  • 607
  • 775
0

Gci and Dir or ls are all aliases to Get-ChildItem.
They only use wildcards in the filter option not regular expressions.
To include only basenames consisting only of numbers you could:

Get-ChildItem -Recurse -Filter "*.jpg" |
  Where-Object BaseName -match "^[0-9]+$"|
    Rename-Item -NewName { $_.Name  -replace '([0-9]+)\.jpg','$1a.jpg'} -whatif

If the output seems ok, remove the -whatif in the last line.

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

try this

Get-ChildItem "c:\temp" -recurse -file -Filter "*.jpg" | 
    where Basename -match "^\d$" | 
        Rename-Item -NewName {$("{0}{1}" -f $_.basename, "a.jpg")}
Esperento57
  • 16,521
  • 3
  • 39
  • 45