Показать полную графическую версию : Переименование имени файла fb2 в соответствии с тэгами
DenchikK
07-11-2019, 10:35
Имеются множество книжек с не пронумированными сериями - ни в имени файла, ни в секции sequence.
Вручную нумировать - долго, файлов много.
Пока идея пришла такая, чтоб книги шли в порядке их выхода, считывать первые 30 строк книги, из нужных тэгов брать информацию и формировать имя файла:
Фамилия Имя - Серия 2010-02-03 - Название.fb2
<first-name>Имя</first-name>
<last-name>Фамилия</last-name>
<sequence name="Серия" />
<book-title>Название</book-title>
<date value="2010-02-03">03 February 2010</date>
Несколько дней читаю форумы, справки, но пока даже не понимаю, как подступиться к решению вопроса.
Имеются множество книжек с не пронумированными сериями - ни в имени файла, ни в секции sequence.
Вручную нумировать - долго, файлов много.
Пока идея пришла такая, чтоб книги шли в порядке их выхода, считывать первые 30 строк книги, из нужных тэгов брать информацию и формировать имя файла:
Фамилия Имя - Серия 2010-02-03 - Название.fb2
<first-name>Имя</first-name>
<last-name>Фамилия</last-name>
<sequence name="Серия" />
<book-title>Название</book-title>
<date value="2010-02-03">03 February 2010</date>
Несколько дней читаю форумы, справки, но пока даже не понимаю, как подступиться к решению вопроса.
Почему именно 30 строк, где располагаются данные теги?
Можно прикрепить пример файла такой книги?
DenchikK
07-11-2019, 15:26
Почему именно 30 строк, где располагаются данные теги? »
<?xml version="1.0" encoding="utf-8"?>
<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
<description>
<title-info>
<genre>detective</genre>
<author>
<first-name>Евгений</first-name>
<middle-name>Евгеньевич</middle-name>
<last-name>Сухов</last-name>
<id>1212f327-2a83-102a-9ae1-2dfe723fe7c7</id>
</author>
<book-title>Бросок на выстрел</book-title>
<annotation>
<p>Вдали от*города журналист Аристарх Русаков обнаружил труп мужчины. Убитым оказался водитель риелторской компании Василий Леваков. Журналист попытался поговорить с*важной свидетельницей*– подружкой убитого, но, как*выяснилось, девушка пару дней назад погибла при*странных обстоятельствах. Тогда Русаков отправился в*охотхозяйство, куда часто приезжал с*компанией Леваков. И*здесь всплыл один странный факт: незадолго до*убийства в*охотхозяйстве бесследно пропал заядлый охотник Востриков. Пропал он глубокой ночью, в*самом лучшем месте для*засады на*кабанов, прозванном Афонькиной протокой…</p>
</annotation>
<keywords>журналистское расследование,расследование преступлений,остросюжетные детективы</keywords>
<date value="2015-01-01">2015</date>
<coverpage>
<image l:href="#cover.jpg">
</image>
</coverpage>
<lang>ru</lang>
<sequence name="Расследования криминального репортера">
</title-info>
<document-info>
<publisher>
<first-name>
</first-name>
<last-name>Литагент «1 редакция»</last-name>
Отсмотрел несколько книг - обычно последняя из искомых строк располагается не ниже 28 строки (если нет тэга <middle-name> и проч). Я взял 30 строк с подстраховкой, но может я и не прав.
DenchikK, ещё раз:
…пример файла такой книги? »
а лучше — несколько примеров (коль речь ведётся про «серии»), упакованных в архив.
но может я и не прав. »
Без «может». В xml вообще нет понятия «строка».
DenchikK
07-11-2019, 21:20
В xml »
Что то я не подумал про xml.
Я тупо в лоб пробовал - рассматривая файл, как текстовый с разметкой, зачищая не нужный мусор.
В лоб не получилось и с xml - немного поискав, я так и не понял, как под мои нужды подставить то, что я нашёл.
Но я на одном форуме нашёл вариант с использованием функции _StringBetween.
Всё вроде здорово, всё как я и хотел, и получилось проще, чем я пытался до этого.
Но опять возникла проблема - с самым главным параметром - датой.
Я не могу пока придумать, как проще из этого:
<date value="2010-02-03">03 February 2010</date>
вычленить это:
2010-02-03
Пока в голову приходят безумные способы.
упакованных в архив »
Да нет никаких архивов. Есть книжки одной серии, уже отредактированных, лежащих в одной дирректории, с одним тэгом серии, которые я хочу упорядочить по дате.
Разные серии - разные дирректории.
Теперь бы понять, как дату вычленить, чтоб назначить переменной.
Вариант для переименования одного файла, прикрутить пакетную обработку, думаю, несложно будет
Local Const $APP_NAME = "fb2renamer"
Local Const $APP_VERSION = "0.1"
Local Const $APP_TITLE = $APP_NAME & " v" & $APP_VERSION
Local $g_oXML
Main()
Func _ReadXMLNodeText($oXMLobj, $sNode)
Local $result = $oXMLobj.SelectSingleNode($sNode)
If IsObj($result) Then
Return $result.text
Else
Return ""
EndIf
EndFunc ;==>_ReadXMLNodeText
Func _ReadXMLNodeAttrib($oXMLobj, $sNode, $sAttrib)
Local $sXPath = $sNode & "[@" & $sAttrib & "]"
Local $result = $oXMLobj.SelectSingleNode($sXPath)
If IsObj($result) Then
Return $result.getAttribute($sAttrib)
Else
Return ""
EndIf
EndFunc ;==>_ReadXMLNodeAttrib
Func _GetParentDir($sFileName)
Return StringLeft($sFileName, StringInStr($sFileName, "\", 0, -1) - 1)
EndFunc ;==>_GetParentDir
Func _GetFileName($sFileName)
Return StringTrimLeft($sFileName, StringInStr($sFileName, "\", 0, -1))
EndFunc ;==>_GetFileName
Func _GetNewName($sFile)
If $g_oXML.load($sFile) Then
Local $result
Local $sLastName, $sMiddleName, $sFirstName, $sBookTitle, $sSequenseName, $sSequenseNumber, $sDate
Local $oNode = $g_oXML.SelectSingleNode("//FictionBook/description/title-info")
$sLastName = _ReadXMLNodeText($oNode, "author/last-name")
$sMiddleName = _ReadXMLNodeText($oNode, "author/middde-name")
$sFirstName = _ReadXMLNodeText($oNode, "author/first-name")
$sBookTitle = _ReadXMLNodeText($oNode, "book-title")
$sSequenseName = _ReadXMLNodeAttrib($oNode, "sequence", "name")
$sSequenseNumber = _ReadXMLNodeAttrib($oNode, "sequence", "number")
$sDate = _ReadXMLNodeAttrib($oNode, "date", "value")
If $sDate == "" Then
$oNode = $g_oXML.SelectSingleNode("//FictionBook/description/document-info")
$sDate = _ReadXMLNodeAttrib($oNode, "date", "value")
EndIf
; Новое имя файла:
Local $sNewFileName = "" _
& $sLastName & " " _
& $sFirstName & " " _
& $sMiddleName & " - " _
& $sSequenseName & " " _
& ($sSequenseNumber <> "" ? "(" & $sSequenseNumber & ")" : "") & " " _
& $sDate & " - " _
& $sBookTitle _
& ".fb2"
$sNewFileName = StringRegExpReplace($sNewFileName, "\ +", " ")
$sNewFileName = StringReplace($sNewFileName, " - - ", " - ")
Return $sNewFileName
Else
SetError(1) ; 1 == file not found
Return ""
EndIf
EndFunc ;==>_GetNewName
Func _DisplayHelp()
MsgBox(0, $APP_TITLE, "" _
& @ScriptName & " [ -y ] FILE1 FILE2 ... FILE(n)" & @CRLF _
& @CRLF _
& @TAB & "-y" & @TAB & "Переименовать файлы вместо тестирования" & @CRLF _
)
Exit 0
EndFunc ;==>_DisplayHelp
Func _PickUpNewName($sFileName)
Local $sNewName = $sFileName
Local $iCount = 1
While True
If FileExists($sNewName) Then
$sNewName = StringRegExpReplace($sNewName, " \([0-9]+\).fb2", " \(" & $iCount & "\).fb2")
If @extended = 0 Then $sNewName = StringReplace($sNewName, ".fb2", " (" & $iCount & ").fb2")
Else
ExitLoop
EndIf
$iCount += 1
WEnd
Return $sNewName
EndFunc ;==>_PickUpNewName
Func _RenameSingleFile($bTestMode, $sFileName)
Local $sOldFullName = FileGetLongName($sFileName, 1)
Local $sOldFileName = _GetFileName($sOldFullName)
Local $sFolderName = _GetParentDir($sOldFullName)
Local $sNewFileName = _GetNewName($sOldFullName)
Local $sNewFullName = _PickUpNewName($sFolderName & "\" & $sNewFileName)
$sNewFileName = _GetFileName($sNewFullName)
If $bTestMode Then
Local $iBtn = MsgBox(4, $APP_TITLE, "" _
& "Папка: " & @CRLF _
& $sFolderName & @CRLF & @CRLF _
& "Имя книги:" & @CRLF _
& $sOldFileName & @CRLF & @CRLF _
& "Новое имя: " & @CRLF _
& $sNewFileName & @CRLF & @CRLF _
& @CRLF _
& "Переименовать?" _
)
If $iBtn = 6 Then FileMove($sOldFullName, $sNewFullName)
Else
FileMove($sOldFullName, $sNewFullName)
EndIf
EndFunc ;==>_RenameSingleFile
Func _QuitWithMessage($sMessage, $iMsgBoxCode = 0, $iExitCode = 0)
MsgBox($iMsgBoxCode, $APP_TITLE, $sMessage)
Exit $iExitCode
EndFunc ;==>_QuitWithMessage
Func Main()
$g_oXML = ObjCreate("Microsoft.XMLDOM")
If Not IsObj($g_oXML) Then _QuitWithMessage("Ошибка инициализации XML :(", 16, 1)
Local $bOptTestMode = True
If $CmdLine[0] = 0 Then _DisplayHelp()
For $i = 1 To $CmdLine[0]
Select
Case $CmdLine[$i] = "/?"
_DisplayHelp()
Case $CmdLine[$i] = "-y"
$bOptTestMode = False
Case FileExists($CmdLine[$i])
_RenameSingleFile($bOptTestMode, $CmdLine[$i])
EndSelect
Next
EndFunc ;==>Main
Да нет никаких архивов. »
Я хотел, чтобы Вы упаковали несколько образцов файлов в архив.
Какое, однако, странное решение... Хотя бы потому, что AutoIt не сможет забраться в zip-архив.
Для подобного лучше подойдёт Total Commander или Double Commander: инструмент группового переименования и один из плагинов для получения инфи из файлов FB2 (eBookInfo WDX (http://wincmd.ru/plugring/eBookInfoWdx.html), Fast Fb2 wdx (http://wincmd.ru/plugring/FastFb2.html) или поновее Fast Fb2 Epub (http://wincmd.ru/plugring/FastFb2_Epub.html) от того же автора).
oz84, ну, автор хотел скрипт — он его получил.
К этому, однако, странному решению поддержку zip-архивов прикрутить - минутное дело, соответствующий UDF (https://www.autoitscript.com/forum/topic/73425-zipau3-udf-in-pure-autoit/) существует давно.
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.