Войти

Показать полную графическую версию : [решено] Переименовать файл по содержимому


deniskx
18-01-2015, 19:23
Приветствую. Помогите, пожалуйста, я не спец.
Есть очень много файлов default.htm, каждый лежит в своей папке. Это html страницы, внутри у каждой из них есть тэг <title>Название страницы</title>. Как бы переименовать каждый файл default.htm в Название страницы.html ? Повторюсь, каждый в своей папке, так что пересечений не будет.

И еще в названии страницы присутствует символ / (например русское / английское название) его надо на что-то заменить. И может быть еще какие-то запрещенные символы.

Georgio
18-01-2015, 21:40
@echo off

set "dir=D:\Test"

for /f "delims=" %%i in ('"2>nul dir/a-d/b/s "%dir%\default.htm""') do (
pushd "%%~dpi"
for /f "delims=" %%j in ('powershell "($x='*'+((gc 'default.htm')-match '<title>..*</title>')+'*'-split '<title>'-split '</title>'-replace '[*\\|:\"\"<>/?</]','_' )[1]"') do (
ren "%%i" "%%j.htm"
)
popd
)

exit/b 0

Iska
18-01-2015, 22:11
Georgio, уж проще целиком на PowerShell, нежели вызывать его N раз.

deniskx, в общем — полностью программно никак. Разве что у Вас удачно окажется исключительно ANSI/1251 (или иная, но одинаковая для всех страниц кодировка, а не какая-нибудь солянка из UTF-8, отданная в KOI-8 и помеченная iso-8859-1, например. Ну, и все entities в <TITLE> также надо преобразовывать в нормальные символы.

Georgio
18-01-2015, 22:27
<title>CMD/BAT - Переименовать файл по содержимому</title> :wink:

Iska
18-01-2015, 22:38
Georgio, ???

deniskx
18-01-2015, 22:48
Georgio, некоторые файлы переименовались, некоторые нет. И кириллица запортилась. Можно PowerShell и vbs скрипты, я не против. Главное, чтобы получилось. Там еще во вложенных папках лежат txt и файлы без расширения, их бы не запортить.
одинаковая для всех страниц кодировка »
Все сохранено с одного сервера, так что кодировка одинаковая. Unix UTF-8 без BOM.

Georgio
18-01-2015, 23:52
некоторые файлы переименовались, некоторые нет. И кириллица запортилась »


Не знаю, что там у Вас такое. Данный код у меня и с UTF-8 отработал, и кириллицу не "запортил". A прикрепить образец файла, который не переименовался, и образец файла, в котором "кириллица запортилась", запаковав оба в архив, -- не вариант? Может, кто-то и разберётся...

Iska
19-01-2015, 02:16
Данный код у меня и с UTF-8 отработал, и кириллицу не "запортил". »
У меня на PowerShell 2.0:
Ошибка в синтаксисе команды.

Мой вариант для UTF-8:
Add-Type -AssemblyName System.Web

$sSourceFolder = "E:\Песочница\0423\01"

if(Test-Path -Path $sSourceFolder -PathType Container) {
Get-ChildItem -Path $sSourceFolder -Include default.htm -Recurse |`
ForEach-Object -Process {
if(-not $_.PSIsContainer) {
Write-Host "$($_.DirectoryName)" -ForegroundColor DarkGreen
Write-Host "`t$($_.Name)" -ForegroundColor Green

$sContent = Get-Content -Path $_.FullName -Encoding UTF8
$oMatch = [System.Text.RegularExpressions.Regex]::Match($sContent, "(?i)<(TITLE)[^<>]*>(?<title>[^<>]+)</\1>")

if($oMatch.Success) {
$sNewName = ([System.Web.HttpUtility]::HtmlDecode($oMatch.Groups.Item("title").Value) -replace '[<>:"/\\|?*]+', "_") + $_.Extension

Write-Host "`t`t$sNewName" -ForegroundColor Cyan

Rename-Item -Path $_.FullName -NewName $sNewName
} else {
Write-Host "`tCan't determine TITLE tag." -ForegroundColor Red
}
}
}
} else {
Write-Host "Can't find source folder [$sSourceFolder]." -ForegroundColor Red
}

deniskx
19-01-2015, 10:36
Данный код у меня и с UTF-8 отработал, и кириллицу не "запортил" »
Все дело в том, что это UTF-8 без BOM и даже Akelpad иногда путает и открывает как 1251, в результате кириллица становится вида "ПароР"
Я пересохранил в Win UTF-8 с BOM и ваш скрипт нормально отработал, кроме одного файла (но у меня очень маленькая выборка пока из 10 случайных файлов, так то их десятки тысяч). От имени остался только конец после точки. Вот с таким
<title>«The Secret Circle. The Temptation.» / «Тайный круг. Искушение.» :: Notabenoid.Com</title>
файл стал Com.htm
Наверное какие-то запрещенные символы остались. А до конвертации "Ошибка в синтаксисе команды" тоже проскакивало.
Хорошо бы сначала переконвертить все default.htm из Unix UTF-8 без BOM (Force) > Win UTF-8 с BOM. Не подскажете скрипт? Или может как-то явно указать эту кодировку в батнике.
Мой вариант для UTF-8 »
Простите мою невежественность, это для Powershell? А как запускать?

Iska
19-01-2015, 11:01
это для Powershell? »
Да.

А как запускать? »
Сохранить в файл с расширением «.ps1», заменив выделенное на путь к Вашим файлам. Однократно разрешить в PowerShell исполнение неподписанных скриптов (если не делали этого ранее). Затем можно пробовать исполнять (лучше сделать копию каталога Ваших файлов и пробовать именно на копии).

deniskx
19-01-2015, 17:46
Iska, спасибо все получилось. Иногда проскакивала ошибка "Слишком длинный путь или имя файла", такие файлы не переименовались, но это не страшно, их немного. Полноценный юникод, даже иероглифы и прочие зарубежные нац. символы в имена файлов перенеслись.

Iska
20-01-2015, 12:48
Иногда проскакивала ошибка "Слишком длинный путь или имя файла", такие файлы не переименовались, но это не страшно, их немного. »
Длинное содержимое тэга «title»? Я, к сожалению, об этом не подумал. Хотя должен был бы.

Попробуйте так:
Add-Type -AssemblyName System.Web

Set-Variable -Name MAX_PATH -Value 260 -Option Constant -ErrorAction SilentlyContinue

$sSourceFolder = "E:\Песочница\0423\01"

if(Test-Path -Path $sSourceFolder -PathType Container) {
Get-ChildItem -Path $sSourceFolder -Include default.htm -Recurse |`
ForEach-Object -Process {
if(-not $_.PSIsContainer) {
Write-Host "$($_.DirectoryName)" -ForegroundColor DarkGreen
Write-Host "`t$($_.Name)" -ForegroundColor Green

$sContent = Get-Content -Path $_.FullName -Encoding UTF8
$oMatch = [System.Text.RegularExpressions.Regex]::Match($sContent, "(?i)<(TITLE)[^<>]*>(?<title>[^<>]+)</\1>")

if($oMatch.Success) {
$sNewName = ([System.Web.HttpUtility]::HtmlDecode($oMatch.Groups.Item("title").Value) -replace '[<>:"/\\|?*]+', "_") + $_.Extension

if(((Join-Path -Path $_.DirectoryName -ChildPath $sNewName).Length) -ge $MAX_PATH) {
$sNewName = $sNewName.Substring((Join-Path -Path $_.DirectoryName -ChildPath $sNewName).Length - ($MAX_PATH - 1))
}

Write-Host "`t`t$sNewName" -ForegroundColor Cyan

Rename-Item -Path $_.FullName -NewName $sNewName
} else {
Write-Host "`tCan't determine TITLE tag." -ForegroundColor Red
}
}
}
} else {
Write-Host "Can't find source folder [$sSourceFolder]." -ForegroundColor Red
}

Полноценный юникод, даже иероглифы и прочие зарубежные нац. символы в имена файлов перенеслись. »
Это Вам свезло, что всё содержимое в одной, заранее известной кодировке.




© OSzone.net 2001-2012