#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
. Извините, я не сделал это более понятным. Также я хочу иметь одно решение, которое обновило бы все файлы в каталоге, и некоторые из них имеют дату в конце файла, а не в начале.