Использование Powershell для изменения порядковых номеров в наборе имен файлов - PullRequest
0 голосов
/ 23 июня 2018

Я новичок в использовании PowerShell (и программирую в этом отношении), все, что я пытаюсь сделать, это переименовать мои файлы).

У меня есть 222 .jpg с именем

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

но моя проблема в том, что они находятся в неправильном порядке, мне нужно поменять их местами, например, мне нужно

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

и наоборот.

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

Есть лиспособ сделать это?В течение нескольких часов я изо всех сил пытался правильно переименовать свои файлы, просто чтобы понять, что они расположены в неправильном порядке, и я испытываю желание просто сделать это по отдельности.

Также, если кто-то может помочь мне изменитьфайлы для чтения

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

, это было бы здорово.

Или, если то, что я спрашиваю, невозможно, у меня есть резервная копия последовательности изображений, прежде чем я начал пытатьсяпереименуйте их, файлы читаются

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

Мне нужно изменить их так, чтобы

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

Ответы [ 4 ]

0 голосов
/ 24 июня 2018

Простой способ изменить порядок:

  • вычесть наибольшее число + 1 из каждого номера файла.
  • , чтобы удалить полученный отрицательный знак, умножить на -1 или использоватьфункция [math]::abs().
  • Чтобы получить число из (базового) имени, регулярное выражение '^REF_1(\d+)?' захватывает () число без начального 1.
  • оператор строки формата "REF.{0:0000}.jpg" -f используется для создания имени, вставляя вычисленное новое число с 4 знаками
  • При изменении префикса существует опасность перезаписи файла с другого конца.

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

Если выходные данные выглядят нормально, удалите конечный параметр -WhatIf.

Пример последней строки вывода:

Что если: Выполнение операции «Переименовать файл» для цели »Элемент: REF_10222.jpg
Назначение: REF.0001.jpg ".

0 голосов
/ 24 июня 2018

Следующее работает с переменным количеством файлов, а также выполняет желаемое преобразование имени (в дополнение к изменению порядковых номеров):

# 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

Примечание. Использование -WhatIf позволяет просмотреть команду без ее фактического запуска. Если в предварительном просмотре отображаются предполагаемые операции, удалите -WhatIf, чтобы фактически выполнить его.

Обратите внимание на необходимость использования aux-типа [ref]. переменная для порядкового номера и для его увеличения через свойство .Value в блоке сценария ({ ... }), которое вычисляет новое имя, поскольку блок сценария выполняется в другой области переменных и, следовательно, не может напрямую изменять переменные в области действия вызывающего .

0 голосов
/ 24 июня 2018

Мои предположения:

  • Мы не знаем заранее, всегда ли числа в именах файлов следуют друг за другом
  • Мы не знаем заранее количество цифр в этихчисла
  • Я бы взял только файлы, начинающиеся с REF_, за которыми следуют числа и заканчивающиеся расширением jpg

Поэтому я предлагаю решение, которое меняет имя на первое с последним, второе споследнее и так далее:

$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
0 голосов
/ 23 июня 2018

Попробуйте это:

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--
    }

Мне кажется, что это немного неэффективно, так как вам нужно перечислить дважды, но это работает с моими тестовыми файлами, поэтому, надеюсь, будет достаточно для решения вашей непосредственной проблемы.

Первый цикл добавляет уникальный «тег» к имени файла, который позже отбрасывается - это необходимо, в противном случае вы столкнетесь с конфликтами (например, если вы попытаетесь назвать «REF_10001» значением «REF_10222», он потерпит неудачу, так как последний уже существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...