удалить дату из имени файла программно

#regex #batch-file #powershell #batch-rename

#регулярное выражение #пакетный файл #powershell #пакетное переименование

Вопрос:

Я пытаюсь найти решение для удаления некоторых дат из имен файлов программно. Мои файлы имеют следующий формат:

net_20110909_servercleanup.pdf

или

net_servercleanup_20110909.pdf

Я использовал решение, опубликованное ниже (также найдено в Stack Overflow), чтобы обновить некоторые имена файлов, но в идеале у меня было бы одно решение, которое могло бы обновить все файлы в моих каталогах. Я бы хотел удалить дату и одно из подчеркиваний, чтобы конечный файл выглядел так:

net_servercleanup.pdf

Я бы хотел сделать это из пакетного файла или PowerShell. Я видел некоторые решения, которые выполняют что-то подобное с помощью регулярных выражений, но я недостаточно знаю о них, чтобы создать что-то, что будет работать. Любые предложения о том, как это сделать?

 $filelist = (get-childitem c:folder | Where-Object {$_.mode -match "a"} | foreach-object      {$_.name})
foreach ($file in $filelist)
{
    $len = $file.length
    $newname = $file.substring(0,$len -13)
    $newname = $newname   '.txt'
    Rename-Item C:folder$file $newname
    clear-variable newname, len
}
 

Ответ №1:

PowerShell, непроверенный, но должен работать:

 $filelist = Get-ChildItem C:folder | Where-Object {$_.Mode -match "a"} `
    | Foreach-Object {$_.FullName}

foreach ($fullpath in $filelist)
{
    $newpath = $fullpath -replace "_(19|20)[0-9]{6}"
    Rename-Item -Path $fullpath -NewName $newpath -WhatIf
}
 

_(19|20)[0-9]{6} Регулярное выражение соответствует следующему шаблону: сначала «_», затем «19» или «20», а затем любые шесть цифр. Если у вас есть имена файлов, в которых дата не соответствует вашему примеру, вам может потребоваться изменить регулярное выражение, чтобы перехватить их все.

-WhatIf Переключатель позволяет выполнять «пробный запуск», т.Е. тестировать командлеты, такие как Remove-Item, фактически не выполняя никаких файловых операций. Удалите его, когда все будет выглядеть нормально, и вы будете готовы приступить к фактическому переименованию.

Комментарии:

1. разве это не должно быть 6 цифр? (последние две цифры года, месяца, дня)

2. Это было 6. Но потом я немного отвлекся, извините. ) Отменено.

3. Спасибо @AlexanderObersht это работает хорошо. Я -WhatIf тоже ценю совет, я не знал об этом.

Ответ №2:

Я не знаю, что это за язык (?), Но на C я бы сделал это, разделив его на части на основе вашего разделителя (в данном случае подчеркивания). В принципе, я бы получил подстроку от начала до символа перед первым подчеркиванием, сохранил ее в потоке (точнее, в stringstream), получил подстроку от символа после первого подчеркивания до символа перед вторым подчеркиванием, … и так далее. а затем из потока я бы получал фрагменты один за другим и проверял, является ли это целым числом, если это целое число, я отбрасываю его, в противном случае оно добавляется к строке, если строка не пуста, тогда я добавляю разделитель (символ подчеркивания) перед добавлением фрагмента.

Я мог бы написать код на c , но я не уверен, поможет ли это

Комментарии:

1. Приведенный выше пример — PowerShell. Я не уверен, что смогу что-то сделать с C , но спасибо за идеи и ответ.

Ответ №3:

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

 get-childitem c:folder | Where-Object {$_.mode -match "a"} | foreach-object {
  rename-item $_.FullName ($_.FullName -replace '_d{8}') -WhatIF
}
 

Удалите -whatif, чтобы фактически выполнить переименование. параметр -replace принимает регулярное выражение, которое соответствует символу подчеркивания, за которым следуют 8 цифр. Поскольку вы не указываете, чем заменить совпадение, оно заменяется пустой строкой.

Обратите внимание, что при этом все файлы переименовываются в одно и то же имя файла, что приводит к ошибке Rename-Item, если файл существует. Если они находятся во вложенных вложенных папках, и вы хотите перебрать их все, вам нужно добавить параметр -Recursive в get-childitem .

Комментарии:

1. Спасибо за решение. Это также сработало, но я пометил решение, предоставленное Александром, поскольку оно было опубликовано первым, я полагаю, и у меня пока недостаточно репутации, чтобы проголосовать за вас. Я столкнулся с ошибками из-за наличия нескольких файлов с одинаковым возможным именем.

Ответ №4:

попробуйте это регулярное выражение:

 _d{8}
 

и заменить на empty . это соответствует _20110909

net_20110909_servercleanup.pdf или net_servercleanup_20110909.pdf

и результат есть net_servercleanup.pdf .

Комментарии:

1. Спасибо Риа. Это то же самое регулярное выражение, которое использовалось в решении Стивена, поэтому я предполагаю, что оно также будет работать.

Ответ №5:

Поскольку это также помечено как пакетное,

Этот код использует for /f команду для удаления цифр и символов подчеркивания из имени файла, сохраняя первый и второй оставшиеся элементы, соединенные знаком подчеркивания, а затем переименовывает файл.

 @echo off
    setlocal enableextensions disabledelayedexpansion

    for /r "c:somefolder" %%f in ("net_*.pdf"
    ) do for /f "tokens=1,2 delims=_0123456789" %%a in ("%%~nf"
    ) do echo ren "%%~ff" "%%a_%%b%%~xf"
 

Для тестирования ren перед командой ставится префикс echo command . Если вывод правильный, удалите echo

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

Комментарии:

1. Спасибо за ответ. Я не пошел с этим решением, потому что многие из моих файлов не начинаются с. net_date Некоторые начинаются с app_date . Извините, я не сделал это более понятным. Также я хочу иметь одно решение, которое обновило бы все файлы в каталоге, и некоторые из них имеют дату в конце файла, а не в начале.