Using Powershell to reverse the sequence numbers i

2019-07-13 02:13发布

I am new to using PowerShell (and coding for that matter), all I'm trying to do is rename my files).

I have 222 .jpg's that are named

"REF_10001.jpg" 
"REF_10002.jpg" 
"REF_10003.jpg" 
etc

but my problem is that they are in the wrong order, I need to reverse them, for example I need

"REF_10001.jpg" --> "REF_10222.jpg"

and vice versa.

"REF_10222.jpg" --> "REF_10001.jpg"

Is there a way to do this? I have been struggling for hours to rename my files properly, just to realize they are in the wrong order, I am tempted to just go do them individually at this point.

Also if someone could help me to change the files to read

"REF.0001.jpg" 
"REF.0002.jpg" 
etc. 

that would be great.

Or if what I'm asking isn't possible, I have a back up folder of my image sequence before i started trying to rename them, the files read

_0221_Layer 1.jpg
_0220_Layer 2.jpg
...
_0000_Layer 222.jpg

I need to change them so that

"_0221_Layer 1.jpg"    -->  "Ref.0001.jpg"
...
"_0000_Layer 222.jpg"  -->  "Ref.0222.jpg"

4条回答
Summer. ? 凉城
2楼-- · 2019-07-13 02:41

My assumptions:

  • We do not know in advance if the numbers in the file names always follow each other
  • We do not know in advance the number of digits in these numbers
  • I would only take files starting REF_ followed by numbers and ending with the extension jpg

So I propose a solution that reverses the first name with the last one, the second with the last before and so on :

$DirWithFiles="C:\Temp\DirWithFilesToRename"

#Creation to new dir for copy
$Temporatydir=  [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
New-Item -ItemType Directory $Temporatydir

#get all file jgp with format REF_ + Number + .jpg and order by number
$ListFile=Get-ChildItem $DirWithFiles -File -Filter "REF_*.jpg" | where BaseName -Match "^REF_\d{1,}$" | select Fullname, Name, @{N="Number";E={[int]($_.BaseName -split '_')[1]}} | sort Number

#copy files into new temporary dir and rename 1 position by N position, 2 by N-1, 3 by N - 2 etc...
for ($i = 0; $i -lt ($ListFile.Count / 2 ); $i++)
{ 
    Copy-Item $ListFile[$i].FullName "$Temporatydir\$($ListFile[$ListFile.Count-$i - 1].Name)" -Force
    Copy-Item $ListFile[$ListFile.Count-$i - 1].FullName "$Temporatydir\$($ListFile[$i].Name)" -Force
}

#Copy all files in temporary dir to initial dir with overwriting
Get-ChildItem $Temporatydir | Copy-Item -Destination $DirWithFiles


#delete temporary dir
Remove-Item $Temporatydir -Recurse
查看更多
放我归山
3楼-- · 2019-07-13 02:44

A simple method to reverse the order is:

  • subtract the highest number+1 from each file number.
  • to remove the resulting negative sign multiply with -1 or use the [math]::abs() function.
  • To get the number from the (Base)Name a Regular Expression '^REF_1(\d+)?' captures () the number without the leading 1.
  • a format string operator "REF.{0:0000}.jpg" -f is used to create the name inserting the calculated new number with 4 places
  • As the prefix changes there is danger overwriting a file from the other end.

Get-ChildItem REF_1*.jpg | 
  Where-Object BaseName -match '^REF_1(\d+)?' |
    Rename-Item -NewName {"REF.{0:0000}.jpg" -f (-1 *($Matches[1]-223))} -whatif

If the output looks OK remove the trailing -WhatIf parameter.

Sample output last line:

What if: Performing the operation "Rename File" on target "Item: REF_10222.jpg
Destination: REF.0001.jpg".

查看更多
啃猪蹄的小仙女
4楼-- · 2019-07-13 02:56

Try this:

Get-ChildItem ".\Pics\*.jpg" | 
    ForEach-Object {$i = 1} {
            Rename-Item  -LiteralPath $_.FullName -NewName "$($_.BaseName)-$i.jpg"
            $i++
    }

Get-ChildItem ".\Pics\*.jpg" | 
    ForEach-Object {$j = 222} {
        Rename-Item  -LiteralPath $_.FullName -NewName "REF_$("1{0:0000}" -f $j).jpg"
        $j--
    }

It's seems a bit inefficient to me, in that you need to enumerate twice, but it works on my test files, so will hopefully be good enough to resolve your immediate problem.

The first loop adds a unique 'tag' to the filename that is later discarded - this is needed otherwise you end up with clashes (e.g. if you try to name "REF_10001" to "REF_10222", it will fail since the latter already exists.

查看更多
霸刀☆藐视天下
5楼-- · 2019-07-13 03:02

The following works with a variable number of files and also performs the desired name transformation (in addition to reversing the sequence numbers):

# Enumerate the files in reverse alphabetical order - which thanks to the 0-padding
# is equivalent to the reverse sequence-number order - and rename them with 
# an ascending 0-padded sequence number.
# Note that in-place renaming is only possible because the new filename pattern
# - REF.*.jpg - doesn't conflict with the old one, REF_1*.jpg
$iref = [ref] 0  # sequence-number helper variable
Get-ChildItem -Filter REF_1*.jpg | Sort-Object Name -Descending |
  Rename-Item -NewName { 'REF.{0:0000}.jpg' -f (++$iref.Value) } -WhatIf

Note: The use of -WhatIf previews the command without actually running it. If the preview shows the intended operations, remove -WhatIf to actually perform it.

Note the need to use a [ref]-typed aux. variable for the sequence number and to increment it via its .Value property in the script block ({ ... }) that calculates the new name, because the script block runs in a different variable scope and therefore cannot directly modify variables in the caller's scope.

查看更多
登录 后发表回答