После грандиозной работы над ошибками (тык), начинаем отвечать на злободневный вопрос — что делать, если лог FreeFileSync вернул кучу файлов с непомерно массивными именами файлов?
Снова обратимся к магии PowerShell и попробуем отделить путь первичного файла от пути зеркалирования, отбросив всё не очень нужное.
После работы прошлого скрипта у нас имеется файл errors.txt. Вот из него мы и попытаемся добыть все пути к проблемным файлам.
Для начала код скрипта:
# Задаем путь к файлу с ошибками из лога
$logFile = "errors.txt"
# Задаём путь к выходному файлу
$outfile = "out.txt"
# Читаем содержимое файла и ищем строки, содержащие текст в кавычках
$files = Select-String -Path $logFile -Pattern '"(.*?)"' -Encoding default
# Извлекаем только текст между кавычками
$results = $files | ForEach-Object { if ($_ -match '"(D:\\.*?)"') { $matches[1] } }
# Выводим результаты
$results | ForEach-Object { Write-Output $_ } | Out-File $outfile -Force
Обратите внимание на строку:
$results = $files | ForEach-Object { if ($_ -match '"(D:\\.*?)"') { $matches[1] } }
Здесь происходит самое важное: цикл пробегает по переменной $files, которая в свою очередь содержит результат работы командлета Select-String, выбораживает оттуда все пути к проблемным файлам, чей адрес начинается с целевого диска зеркалирования (у меня это диск D) и всё, что нашлось отправляется прямиком в переменную $results.
В своих реалиях переделайте строку на собственный вкус. Главное, чтобы шаблон с упоминанием диска был корректный. В итоге, всё, что удалось накопать скрипту попадает в файл out.txt.
Важный момент номер раз: на заре написания этих скриптов мне пришлось знатно поиграть в угадайку с кодировками файлов и правилами переноса строк. Обращайте на это максимально пристальное внимание, чтобы не получить вместо кириллических путей пачку вопросительных знаков.
Теперь можно смело сказать, что чудо свершилось и мы получили выстраданный список файлов, которые ни в какую не хотят зеркалится на нашу smb-шару. Попробуем их переименовать.
Важный момент номер два: результатом работы скрипта, приведённого ниже, будет массовое переименование общих файлов из основного хранилища. Думаю, стоит напомнить, что данная операция негативно отразится на ярлыках, которые ссылаются на упомянутые файлы, а также на пользовательский опыт нейминга. Очень важно понимать, какие будут последствия, и осознавать всю ответственность за свои дальнейшие действия. Если что — я Вас предупреждал и призывал к анализу кода. Удачи!
Собственно, код скрипта для массового переименования файлов:
# Укажите путь к файлу со списком путей
$listOfPaths = Get-Content -Path "out.txt"
# Максимальная длина имени файла
$maxLength = 100
foreach ($filePath in $listOfPaths)
{
# Получаем имя файла и директорию
# Получаем имя файла без расширения
$fileName = [System.IO.Path]::GetFileNameWithoutExtension($filePath)
# Получаем расширение файла
$fileExtension = [System.IO.Path]::GetExtension($filePath)
$directory = [System.IO.Path]::GetDirectoryName($filePath)
# Удаляем точки из имени файла
$newFileName = $fileName -replace '\.', ''
# Проверяем длину нового имени файла
if ($newFileName.Length -gt $maxLength)
{
# Если имя файла превышает максимальную длину - сокращаем имя файла
$newFileName = $newFileName.Substring(0, $maxLength - 4)
}
# Добавляем расширение к новому имени
$newFileName += $fileExtension
# Формируем новый путь
$newFilePath = Join-Path -Path $directory -ChildPath $newFileName
# Переименовываем файл
Rename-Item -Path $filePath -NewName $newFilePath
# Выводим сообщение
Write-Output "Переименован: $filePath -> $newFilePath"
}
# Ждём действия пользователя
Read-Host
Здесь я не добавлял никаких обработчиков ошибок и проверки наличии файла. Подразумевается, что упоминаемый файл лежит там, где указано в файле журнала программы FreeFileSync.
Кстати, скрипт сносит начисто все точки из имен файлов, чтобы не возникло недопонимания в форматах файлов в дальнейшем. Возможно, это деструктуризирует даты в именах, но в целом на читаемость имени это не повлияет.
Количество символов в длине имени я ограничил сотней. Можете причесать переменную $maxLength по своему вкусу и под свои потребности.