Home > Mobile >  How to rename folders to put the year first using Powershell
How to rename folders to put the year first using Powershell

Time:01-04

I'm trying to organize some old photos that are split into many different folders. All of the folder names do contain the year, but almost always at the end of the folder name. This doesn't work very well when I'm trying to sort all of my photos from the past 20 years. I'm trying to write a script that would loop through all of the folder names and move the year (YYYY) to the beginning of the folder name.

Current Folders:

  • The best trip ever 2012
  • Visiting relatives 2010
  • 2017 trip
  • Old photos from 2001

Convert to:

  • 2012 The best trip ever
  • 2010 Visiting relatives
  • 2017 trip
  • 2001 Old photos from

I am not very familiar with powershell so I've spent a few hours fiddling with regex and the necessary scripts to filter to the right subset of folder names (that start with a letter and contain a 4 digit year) but I'm struggling to actually rename these successfully.

Here's what I have:

$folders = Get-ChildItem -Path C:\Users\User\pictures\ | Where-Object { $_.Name -match '^[a-zA-Z]. [0-9]{4}' }
foreach ($folder in $folders) 
        { $folder.Name.Split() | Where {$_ -match "[0-9]{4}"}
            Rename-Item -Path $folder-NewName  "$($Matches[0])_$folder.Name"
}

Any help is appreciated!

CodePudding user response:

If you use the -match operator with a regex that captures the name parts of interest via capture groups ((...)), you can rearrange these name parts, as reflected in the automatic $Matches variable variable, in a delay-bind script block passed to the Rename-Item call:

Get-ChildItem -Directory C:\Users\User\pictures |
  Where-Object Name -match '^(. ?) ?\b(\d{4})\b(.*?)$' |
    Rename-Item -WhatIf -NewName { 
      '{0} {1}{2}' -f $Matches.2, $Matches.1, $Matches.3 
    }

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.

For an explanation of the regex and the ability to interact with it, see this regex101.com page.


Note: The following simplification, which uses the -replace operator, works in principle, but, unfortunately, reports spurious Source and destination path must be different errors as of PowerShell 7.2.1, for all directories whose name either doesn't contain a 4-digit year or already has it at the start of the name:

# !! Works, but reports spurious errors as of PowerShell 7.2.1
Get-ChildItem -Directory C:\Users\User\pictures
  Rename-Item -WhatIf -NewName { $_.Name -replace '^(. ?) ?\b(\d{4})\b(.*?)$' }

The reason is Rename-Item's unfortunate behavior of complaining when trying to rename a directory to its existing name (which happens when the -replace operation doesn't find a regex match and therefore returns the input string as-is), which should be a quiet no-op, as it already is for files - see GitHub issue #14903.

  •  Tags:  
  • Related