1

I have a folder with media files named by timestamp like following yyyyMMdd_HHmmss_*.*. I need to rename them to yyyy-MM-dd HH-mm-ss *.*

For example I need to rename file 20181019_210353_BURST2.jpg to 2018-10-19 21-03-53 BURST2.jpg There is a my ugly approach

PS E:> gci | Rename-Item -NewName { $_.Name.Substring(0,4) + '-' + $_.Name.Substring(4,2) + '-' + $_.Name.Substring(6,2) + ' ' + $_.Name.Substring(9,2) + '-' + $_.Name.Substring(11,2) + '-' + $_.Name.Substring(13,2) + $_.Name.Substring(15) }

What is the right command to obtain my purpose?

Loom
  • 9,768
  • 22
  • 60
  • 112

2 Answers2

6

If it is concision you're looking for, you can use the -replace operator with the following regex:

Get-ChildItem -File -Filter *.jpg | Rename-Item -NewName { 
  $_.Name -replace '(^\d{2})?(\d{2})(\d{2})(\d{2})_', '$1$2-$3-$4 '
} -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.

An explanation of the regex, as well as the ability to experiment with it and the substitution expression, can be found on this regex101.com page.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Should the first item be `\d{4}`? – lit Sep 13 '21 at 13:21
  • @lit, no - you can see that if you follow the rege101.com link, where you can experiment with the regex yourself. – mklement0 Sep 13 '21 at 13:36
  • 1
    Ok. So, the `?` between the first two captures allows it to handle both the eight (8) digit data and the six (6) digit time. – lit Sep 13 '21 at 20:53
4

Your method will work, but you will need to provide a -Path parameter to Rename-Item. The short answer is that the string will need to be broken down into the components to use in the new name.

If you want to have some regex fun, you could use something like this. When you are convinced that the files will be renamed correctly, remove the -WhatIf from the Rename-Item command.

Get-ChildItem |
    ForEach-Object {
        if ($_.Name -match '^(....)(..)(..)_(..)(..)(..)(.*)') {
            $NewName = "$($Matches[1..3] -join '-') $($Matches[4..6] -join '-')$($Matches[7])"
            Rename-Item -Path $_.FullName -NewName $NewName -WhatIf
        }
    }
lit
  • 14,456
  • 10
  • 65
  • 119
  • 1
    There's nothing wrong with the OP's command (except, I think, wanting a less cumbersome formulation). In fact, their use of `Rename-Item` with a [delay-bind script block](https://stackoverflow.com/a/52807680/45375) is both more concise and efficient than a `ForEach-Object` solution – mklement0 Sep 13 '21 at 03:00