Home > Blockchain >  PowerShell or CMD - Find and Increment alphabet letter of files (revision management)
PowerShell or CMD - Find and Increment alphabet letter of files (revision management)

Time:11-24

I need some help to automate rename files in a current directory. The following files that can exits in the directory is for example:

AAA111A.txt

AAA111A.pdf

AAA111A.jpg

BBB222B.jpg

BBB222B.pdf

Where the bold letter stand for the revision of the file. What I want is a PowerShell or batch file where it automatically looks what revision letter it is and then increment that revision letter with the next in the alphabet for all files.

Example:

AAA111A.txt -> AAA111B.txt

BBB222B.pdf -> BBB222C.pdf

etc

The letters and numbers before the revision letter and the extension of the file can vary, so used as a wildcard? It is also possible that the file is named like: AAA111A-01.pdf or AAA111A-blabla.pdf

Hopefully someone can make my life easier for this noobie :).

Thank you in advance!

CodePudding user response:

Building off of Abraham's answer, because the use of a scriptblock with parameter to evaluate the replacement is great and not something I knew about before today. I'd just setup a hashtable ahead of time for the replacement letter(s). I'd replace z with aa to avoid conflicts, assuming that doesn't break the naming convention.

$Letters=[hashtable]::new() #unconventional hashtable creation to create a hashtable with case sensitive keys
65..122|?{$_ -lt 90 -or $_ -gt 96}| #this gets up A through Z and a through z, skipping the other characters between the sets
    ForEach-Object{$Letters.add([string][char]$_, [string][char]($_ 1))}
$Letters.'Z'='AA' #manually set rollover case
$Letters.'z'='aa' #manually set rollover case

Once you get that setup you can basically do what Abraham suggested, just referencing the hashtable to get the replacement string.

Get-ChildItem C:\Path\To\Files*.txt|
    Rename-item -NewName {
        [regex]::replace($_.Name, '(?<=^[a-zA-Z0-9] )([a-zA-Z])(?=\W)',{param($old)$Letters[$old.value]})
        }

This has the same failing that Abraham's answer does in that it does not check for file name availability before trying to rename a file. It does solve the case where a file's revision is at Z though. My regex is also a little more flexible for cases where a file is named something like 'AAAA111C-glarb.txt' and will correctly increment it to 'AAAA111D-glarb.txt'.

CodePudding user response:

If you're not on PowerShell core (like me), you can use the Replace() static method on the [regex] class for a more advanced replacement. This gives us some flexibility to change the matched character to it's corresponding integer where we could add 1 to it, then change it back to its equivalent letter:

Get-ChildItem -Path '.\MyPath' | 
    Rename-Item -NewName {
        [regex]::Replace($_.BaseName,
            '[A-Z]$', {
                Param($match)
                $letter_int = [int][char]$match.Value   1
                [char]$letter_int
            }
        )   $_.Extension
    } -WhatIf

This doesn't account for other issues that you may encounter such as duplicate file names, or as Santiago mentioned in the comments, the logic that would be needed if the letter reaches the end of the alphabet.


Remove the -WhatIf safety common parameter when you've dictated that is the result you're after.

CodePudding user response:

Thank you for the answers Abraham and TheMadTechnician! Both are working like a charm. With the Abraham I added a second replace regex with '[A-Z]\b' to get the letter before the character - .

I'm happy and learned a lot. Thanks again

  • Related