Как переместить первые 7 символов имени файла в конец с помощью Powershell - PullRequest
0 голосов
/ 19 сентября 2018

У моей компании миллионы старых отчетов в формате PDF.Они обычно называются в формате: 2018-09-18 - ReportName.pdf

Организация, в которую мы должны их отправить, теперь требует, чтобы мы назвали файлы в следующем формате: Report Name - 2018-09.pdf

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

Спасибо!

Ответы [ 4 ]

0 голосов
/ 19 сентября 2018

Предостережение :

  • Как указывает jazzdelightsme , желаемая операция переименования может привести к конфликтам имен ,учитывая, что вы удаляете компонент дня из ваших дат;например, 2018-09-18 - ReportName.pdf и 2018-09-19 - ReportName.pdf приведут к тому же с тем же именем , Report Name - 2018-09.pdf.

  • В любом случае, я предполагаю, что операция переименованиявыполнено на копиях оригинальных файлов.Кроме того, вы можете создавать копии с новыми именами в других местах с Copy-Item при перечислении оригиналов, но преимущество Rename-Item в том, что оно сообщит об ошибке в случае именистолкновение.

Get-ChildItem -Filter *.pdf | Rename-Item -NewName { 
  $_.Name -replace '^(\d{4}-\d{2})-\d{2} - (.*?)\.pdf$', '$2 - $1.pdf' 
} -WhatIf

-WhatIf превью операция переименования;удалите его для фактического переименования.
Добавьте -Recurse к вызову Get-CildItem для обработки всего каталога поддерево .
Использование -Filter необязательно, но ускоряет обработку.

  • Блок сценария ({ ... }) передается параметру Rename-Item -NewName, который позволяет динамически переименовывать каждый входфайл ($_), полученный из Get-ChildItem с использованием выражения преобразования (замены) строки.

  • Оператор -replace использует regex (регулярное выражение) в качестве первого операнда для выполнения замены строк на основе шаблонов;здесь регулярное выражение разбивается следующим образом:

    • ^(\d{4}-\d{2}) соответствует чему-то вроде 2018-09 в начале (^) имени и - благодаря тому, что заключено в (...) - захватывает, которые совпадают в так называемой группе захвата , на которую можно ссылаться в замещающей строке по ее индексу, а именно $1, поскольку это первая группа захвата.

    • (.*?) фиксирует оставшуюся часть имени файла , исключая расширение в группе захвата $2.

      • ? после .* делает подвыражение нежадным , что означает, что последующие подвыражения также могут совпадать, в отличие отпытается найти как можно больше символов (это поведение по умолчанию, называемое жадный ).
    • \.pdf$ соответствует расширению имени файла (.pdf) в конце ($) - обратите внимание, что регистр не имеет значения.. экранируется как \., потому что здесь предполагается совпадение буквально (без экранирования, . соответствует любому одному символу в однострочной строке).

    • $2 - $1.pdf - замещающая строка, которая определяет, какие группы захвата были захвачены в нужной форме.

Обратите внимание, что любой файл, имя которого не совпадает с регулярным выражением, спокойно остается один, потому что оператор -replace пропускает входную строку, если не найдено совпадений, и Rename-Item ничего не делает, если новое имя совпадает со старымодин.

0 голосов
/ 19 сентября 2018

Это должно работать (добавлено несколько тестовых данных):

$test = '2018-09-18 - ReportName.pdf','2018-09-18 - Other name.pdf','other pattern.pdf','2018-09-18 - double.extension.pdf'

$test | % {
    $match = [Regex]::Match($_, '(?<Date>\d{4}-\d\d)-\d\d - (?<Name>.+)\.pdf')
    if ($match.Success) {
        "$($match.Groups['Name'].Value) - $($match.Groups['Date'].Value).pdf"
    } else {
        $_
    }
}
0 голосов
/ 19 сентября 2018

Примерно так -

Get-ChildItem -path $path | Rename-Item -NewName {$_.BaseName.Split(' - ')[-1] + ' - ' + $_.BaseName.SubString(0,7) + $_.Extension} -WhatIf

Пояснение -

  1. Split выделит имя файла на основе параметра -[-1] указывает PowerShell выбрать последнее из сегрегированных значений.
  2. SubString(0,7) выберет 7 символов, начиная с первого символа BaseName файла.
  3. Удалить -WhatIf чтобы применить переименование.
0 голосов
/ 19 сентября 2018

Get-ChildItem с некоторыми RegEx и Rename-Item может сделать это:

Get-ChildItem -Path "C:\temp" | foreach {

    $newName = $_.Name -replace '(^.{7}).*?-\s(.*?)\.(.*$)','$2 - $1.$3'
    $_ | Rename-Item -NewName $newName
}

RegEx

'(^.{7}).*?-\s(.*?)\.(.*$)' / $2 - $1.$3

  • (^.{7}) соответствует первым 7 символам
  • .*?-\s соответствует любым символам до (и включая) первого найденного - (пробел)
  • (.*?)\. соответствует чему-либо до тех пор, пока первая найденная точка (.)
  • (.*$) не будет соответствовать расширению файла в этом случае
  • $2 - $1.$3 соберет все вместе в измененном порядке

Это не будет работать должным образом, если в имени файла есть несколько точек (.).

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