Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Скрипт для переименовывания файлов с латиницы на русский лад (http://forum.oszone.net/showthread.php?t=347535)

Latinyanin 05-01-2021 15:10 2945073

Скрипт для переименовывания файлов с латиницы на русский лад
 
Привет!
Вот на скрине можно увидеть много файлов формата fb2 подписанных латиницей.

Возможен ли скрипт создать (или как, правильне bat - ник ?) который бы "переподписал" эти самые файлы русскими буквами?
Причем в именах файлов-книг были бы только названия книг без автора.
Такое реально вообще-то?


DJ Mogarych 05-01-2021 15:22 2945075

Реально, но это будет очень криво, и лучше оставить как есть.

YuS_2 06-01-2021 11:53 2945136

Цитата:

Цитата Latinyanin
файлы русскими буквами? »

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

Цитата:

Цитата Latinyanin
Причем в именах файлов-книг были бы только названия книг без автора.
Такое реально вообще-то? »

Если всегда в начале наименования файла присутствует фамилия автора и только фамилия, без инициалов и прочих дополнительных маркировок, то вполне:
powershell
Код:

$folder = '.\BOOKS'
$flt = '*.fb2'
dir $folder -filter $flt|
ren -new {($_.basename -replace '^[^_]*_' -replace '\.\d+$') + $_.extension}


Iska 06-01-2021 15:54 2945178

Коллеги, это опять fb2, то бишь, надо смотреть внутрь xml и брать содержимое тэгов author (/FictionBook/description/title-info/author/first-name, /FictionBook/description/title-info/author/middle-name
/FictionBook/description/title-info/author/last-name) и /FictionBook/description/title-info/book-title.

Fors1k 06-01-2021 17:06 2945196

Цитата:

Цитата Iska
надо смотреть внутрь xml »

Код:

param(
    $path = 'D:\books'
)cls

(gci -File "$path\*.fb2").FullName|%{
    ren $_ (([xml](gc -en UTF8 $_)).FictionBook.description.'title-info'.'book-title'+'.fb2')
}


Iska 06-01-2021 18:22 2945203

Fors1k, кодировка файлов может быть как ANSI/1251, так и UTF-8/65001.

Fors1k 06-01-2021 19:47 2945213

Цитата:

Цитата Iska
кодировка файлов может быть как ANSI »

Я доселе не встречал.
Код:

param(
    $path = 'D:\books'
)cls

(gci -File "$path\*.fb2").FullName|%{$book=[xml]::new()}{
    $book.Load($_)
    ren $_ ($book.FictionBook.description.'title-info'.'book-title'+'.fb2')
}


Uragan66 07-01-2021 01:04 2945227

Latinyanin, всё это элементарно делается специальным софтом для работы с FB2. Не нужны никакие скрипты, да и разобраться неподготовленному юзеру будет проще.
К примеру возьмите эту утилиту - FB2Toolbox , она наиболее подходит для Вашей задачи. Хотя, как выше заметил ув. Iska, всё зависит от структуры файла, как в файле указан тэг author

Iska 07-01-2021 04:26 2945231

Цитата:

Цитата Fors1k
Я доселе не встречал. »

Увы, бывает.

Как и неописанный namespace внутри fb2 :shot:.

YuS_2 08-01-2021 08:58 2945350

Цитата:

Цитата Iska
Увы, бывает. »

Это да, точно...
По мотивам этого топика и идее Iska, "состряпал" скрипт. Не идеальный, со своими недостатками, но свою функцию выполняет на тех файлах, которые у меня давно хранились в куче, безо всякого порядка...
Что делает:
1. Читает рекурсивно каталог на предмет файлов, архивов *.zip, *.fbz (возможно указать другие расширения, но распаковывать будет только формат zip), распаковывает архивы, удаляет их.
2. Считывает fb2.
3. Создает структуру каталогов в формате:
<корневой каталог $out>\<author.'last-name'> <author.'first-name'>\
При наличии авторов более одного, для именования каталога, будет использоваться только первый по списку.
Далее, при наличии серии, создает подкаталог с именем <sequence.name>
4. Перемещает книги в соответствующие каталоги с переименованием, в формате:
<sequence.number>_<sequence.name>_<'book-title'>
5. Упаковывает книги в формате zip (при наличии ключа -fbz)
6. Переименовывает расширение у архивов с книгами из .zip в .fbz (при наличии ключа -fbz. Расширение возможно указать любое другое)

Если в исходном каталоге имелась структура каталогов, её придется удалять вручную... не стал заморачиваться с доп.проверками на "пустой - не пустой"... при желании, можно прикрутить, сложности большой в том нет...

script.ps1
Код:

# http://forum.oszone.net/post-2945350.html#post2945350
# Изменен 15.01.2021
# Примеры запуска из консоли powershell:
# с архивацией целевых файлов:
# .\script.ps1 -in "D:\Books" -out "D:\Out" -fbz
# без архивации:
# .\script.ps1 -in "D:\Books" -out "D:\Out"

param(
        [string]$in = '.\BOOKS',
        [string]$out = '.\BOOKS_OUT',
        [string[]]$include = ('*.fbz','*.zip'),
        [switch]$fbz
)
function expand-zip {
        process {
                try{
                        if ($_.extension -match '\.fbz|\.zip'){
                                if ($_.extension -eq '.fbz'){ren $_.fullname $($_.basename+'.zip')}
                                $zip = gi $($_.fullname -replace '\.fbz','.zip')
                                expand-archive $zip.fullname $zip.directoryname -ea 1
                                del $zip
                        }
                } catch {
                        write-host "ошибка: $_" -for red
                }
        }
}
# https://docs.microsoft.com/ru-ru/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN
$except = '\[|\]|<|>|\*|\"|:|\?|\\|/|\|'
if (!(test-path $out -patht 'Container')){$null = md $out}
$folder = gi $out
dir $in -inc $include -file -rec|expand-zip

dir $in -inc '*.fb2' -file -rec|%{
        $arch,$b,$d,$d_author,$ser = $null,$null,$null,$null,$null
        if ((gc $_.fullname -tot 1) -match 'windows-1251'){
                if ($pscore = $psversiontable.psversion.major -gt 5){
                        $encoding = 'windows-1251'
                } else {$encoding = 'default'}
        } else {$encoding = 'utf8'}
        $book = ([xml](gc $_.fullname -enc $encoding)).fictionbook.description.'title-info'
        $d = $folder.fullname+'\'+(
                (([array]$book.author)[0].'last-name'+' '+([array]$book.author)[0].'first-name') -replace $except
        )
        if(!(test-path $d -patht 'Container')){$d_author = md $d} else {$d_author = gi $d}
        if ($book.sequence.number){
                $b = $d_author.fullname+'\'+($book.sequence.name -replace ' ','-' -replace $except)
                if(!(test-path $b -patht 'Container')){$ser = md $b} else {$ser = gi $b}
                $new = $ser.fullname+'\'+$book.sequence.number+'_'+(
                        (($book.sequence.name -replace ' ','-')+'_'+$book.'book-title')  -replace $except
                )+$_.extension
        } else {
                $new = $d_author.fullname+'\'+($book.'book-title' -replace $except)+$_.extension
        }
        try{mi $_.fullname $new -ea 1} catch {write-host Ошибка: $new - $_ -for red}
        $arch = gi $new
        if ($fbz){
                try{
                        compress-archive $arch.fullname $($arch.directoryname+'\'+$arch.basename+'.zip') -ea 1
                        del $arch
                } catch {
                        write-host Ошибка: $($arch.directoryname+'\'+$arch.basename+'.zip') - $_ -for red
                }
        }
}
dir $folder.fullname -filt '*.zip' -file -rec|ren -new {$_.basename+'.fbz'}


DJ Mogarych 08-01-2021 09:11 2945353

Вероятно, надо предусмотреть присутствие в тэгах символов, которые не могут быть использованы в именах файлов и каталогов.

YuS_2 08-01-2021 09:28 2945355

Цитата:

Цитата DJ Mogarych
которые не могут быть использованы в именах файлов и каталогов. »

Да, тоже подумалось про это и даже частично сделал, здесь:
Код:

-replace '\[|\]'
Но искать список недопустимых символов было просто лень, а после тестов и приемлемой реализации, совсем лень одолела, т.к. на моих книгах не попалось таких символов... :)

Добавлено:
Собственно, fixed, здесь можно пополнять/редактировать:
Код:

$except = '\[|\]|<|>|\*|\"|:|\?|\\|/|\|'
- на основании этого

greg zakharov 08-01-2021 19:56 2945398

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

function ConvertFrom-Translit {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory, ValueFromPipeline)]
    [ValidateNotNullOrEmpty()]
    [String[]]$InputString
  )

  process {
    $par, $map = ([Char[]]'cstyz'), @{
      a = 49; b = 49; v = 68; g = 52; d = 48; e = 48;
      yo = 40;
      zh = 68;
      z = 67; i = 49; y = 64;
      k = 49; l = 49; m = 49; n = 49; o = 49; p = 49;
      r = 50; s = 50; t = 50; u = 50;
      f = 34; h = 35;
      ts = 46;
      ch = 28;
      sh = 43;
    sch = 42;
      yi = 46;
      yu = 43;
      ya = 42
    }

    $InputString.ForEach{
      [Text.Encoding]::Unicode.GetString(
        $(for ($i = 0; $i -lt $_.Length; $i++) {
          if ($_[$i] -eq '_') {
            95, 0
            continue
          }

          ($_[$i] - $map["$($_[$i] -in $par ? $(
            try { $itm = $_.Substring($i, ($$ = $_[$i + 1] -ceq 'c' ? 3 : 2)) } catch {}
            $map.Contains($itm) ? $($itm; $i += (--$$)) : $_[$i]
          ) : $_[$i])"]), 4
        })
      )
    }
  }
}

Пример работы:
Код:

('Loginov_Dolina_Loreien.103821.fb2',
'Loginov_Doletet_do_epsilen_Tukana.142082.fb2',
'Loginov_Dom_u_dorogi.33523.fb2',
'Loginov_Dorogoy_shirokoy.69636.fb2',
'Loginov_Dragotsennee_mnogih_Meditsinskie_hroniki_.33524.fb',
'Loginov_Esche_o_vinegrete.22527.fb2',
'Loginov_Kolodez.22545.fb2',
'Loginov_Kommunalka.33546.fb2').ForEach{
  $_ -replace '(^[^_]*_|\..*)'
} | ConvertFrom-Translit

Итог:
Код:

Долина_Лореиен
Долетет_до_епсилен_Тукана
Дом_у_дороги
Дорогой_широкою
Драгоценнее_многих_Медицинские_хроники_
Еще_о_винегрете
Колодез
Коммуналках

Как видно, проблема в определённых знаках вроде мягкого\твёрдого знака, а также буквы "э". Но, как говрится, это лучше чем ничего, т.е. отсутствие специфических тэгов в фикшн буке.
Более надёжный способ послать запрос в Google Translate (https://translate.google.ru/?sl=auto...2&op=translate) и забрать, скажем, Selenium'ом вполне себе нормально конвертированный текст. Хотя если есть API ключ, то можно с Selenium не заморачиваться, а брать конвертированный текст напрямую.

Latinyanin 09-01-2021 14:59 2945508

Цитата:

Цитата DJ Mogarych
Реально, но это будет очень криво, и лучше оставить как есть. »

как есть - не вариант

DJ Mogarych 10-01-2021 11:31 2945613

Latinyanin, ну вперёд:
Цитата:

Цитата greg zakharov
Долина_Лореиен
Долетет_до_епсилен_Тукана
Дом_у_дороги
Дорогой_широкою
Драгоценнее_многих_Медицинские_хроники_
Еще_о_винегрете
Колодез
Коммуналках »


YuS_2 10-01-2021 11:34 2945616

Цитата:

Цитата Latinyanin
как есть - не вариант »

тут кучу вариантов уже предложили... пользуйтесь тем, который устроит...

Latinyanin 14-01-2021 14:47 2946156

Цитата:

Цитата YuS_2
Если всегда в начале наименования файла присутствует фамилия автора и только фамилия, без инициалов и прочих дополнительных маркировок, то вполне:
powershell »

в том и дело, что окромя фамилии автора есть и имя и прочая,,,,информация.

Цитата:

Цитата YuS_2
тут кучу вариантов уже предложили... пользуйтесь тем, который устроит... »

только седня смог полностью все ответы прочесть, стараюсь всем ответить как могу

Latinyanin 14-01-2021 15:06 2946164

Uragan66,
за утилиту спасибо - насчет сложно разобраться так у меня два скрипта мне норм работают пока

Iska 14-01-2021 15:12 2946167

Latinyanin, да, я бы тоже опробовал вначале именно утилиту.

Latinyanin 14-01-2021 15:27 2946173

Все-таки придется тупо вручную наверное переиеименовывать. Ни один из трех скриптов опыта не дал результата потребного. Хотя с другими книгами опыт был но все также поименованными латиницей

https://yadi.sk/d/QI5RAbZK9aDVnQ

но может не так оформил сам скрипт? Помещал в ту ж папку, что и файлы книг

YuS_2 14-01-2021 21:18 2946231

Вложений: 1
Цитата:

Цитата Latinyanin
Все-таки придется тупо вручную наверное переиеименовывать. »

с таким подходом... многое придется делать вручную :)

Цитата:

Цитата Latinyanin
Ни один из трех скриптов опыта не дал результата потребного. »

Что не удивительно. Вы вообще различия между powershell и cmd не видите/не знаете?

Цитата:

Цитата Latinyanin
Помещал в ту ж папку, что и файлы книг »

скрипт (мой, во всяком случае) можно помещать куда угодно, но с указанием абсолютного пути к каталогу с книгами...

Чтобы вам было попроще, сделал запускающий сценарий cmd (run_me.bat), который запускает необходимый сценарий powershell (script.ps1) - см. приложенный архив с необходимой структурой внутри:
Файл 163381
Книги надо будет поместить в каталог BOOKS, расположенный рядом со скриптом script.ps1
Если упаковка книг не требуется, то в батнике необходимо удалить ключ -fbz
Всё. Запускаем батник и ожидаем выполнения скрипта. Появляющиеся в процессе работы скрипта красные надписи, необходимо читать внимательно и полностью.

Опиум 15-01-2021 16:53 2946325

Цитата:

Цитата Latinyanin
который бы "переподписал" эти самые файлы русскими буквами? »

кто то старался, русские переделывал в транслит, а вы хотите обратно все испортить

Latinyanin 21-01-2021 14:22 2947107

Снова привет!



Порекомендованная программа FB2Toolbox очень помогла с переименовывавнием файлов fb2 книг. Но!
Все-таки мне нужен скрипт небольшой, который бы "допилил" под мои нужды результаты работы FB2Toolbox. На скриншооте
FB2Toolbox.exe
виден список книг одной серии. Скрипт должен добавить в имя файла два компонента:
один пробел перед и после каждого тире(-)
добавить ноль перед каждой цифрой списка от 1 до 9
сама папка с файлами для переименовывания
Возможно?

Может надо отдельную тему создать?

Latinyanin 21-01-2021 15:34 2947118

Порекомендованная программа FB2Toolbox очень помогла с переименовывавнием файлов fb2 книг

Андрей_Ахмедов@vk 16-03-2021 03:32 2952798

Интересно а как .... в предложенном YuS_2 скрипте
1. увеличить рекурсию более 2 уровней в скрипте
2. бороться с флагом "для чтения" который навешивается автоматом на входную и выходную папки
3. вывести обработку ошибок ( скажем так ...... 1 - если нет тега "автор", "название" - оставлять как есть(ныне частенько так спешат верстать фб что их просто нет).... 2 - добавить цифровую составляющую к копиям, что бы не сносилось в ноль....3 - почему то некоторые зип не дают скрипту прочесть теги, только по распаковке)
4. ..... наверное главное))) литература для "чайника" по повершелл.... просто чую что никто этого не сделает))) а хочется понять и разобраться, чтоб самому сделать.
..........
если по п. 1 . еще что то встречается, то вот по п2. в ступоре почему система автоматом вывешивает флаг" для чтения" - остаются исходные файлы.... пробовал вручную менять , но тут же был отшит системой)))

greg zakharov 16-03-2021 11:09 2952833

Андрей_Ахмедов@vk, 1 -Recurse -Depth ...
2. -Force (или просто снять бит)
3. try .. catch .. finally; throw
4. Get-Help

Андрей_Ахмедов@vk 16-03-2021 12:54 2952844

greg zakharov, Get-Help увы не для "чайника" изучавшего древний паскаль во времена эмулятора 8086))... ну еще чуток ЛУА для сталкера - мелкие правки для внесения своей "великой лепты" в игру и чужие моды )).....
По хелперу надо иметь представление что именно ищещь.
А основная литература либо для сисадминов, либо затрагивает больше именно те моменты для чего в общем то и делался повершелл - администрирование(ну кроме банального "Привет мир" в начале).
Вот что из отряда прикладных повседневных задач для пользователей из литературы бы?
И СПАСИБО!
За внимание и ответ.

greg zakharov 16-03-2021 13:18 2952846

Андрей_Ахмедов@vk, увы, но проще способа нет, ибо когда лично брался за Powershell (тогда ещё Monad), вообще не было никакой документации, так что лучше с Get-Help и начать. Проще никак. В моём случае мне подспорьем был опыт программирования на C#, чтение спецификаций и монографии Рихтера о CLR, а также много часов экспериментов с кодом и отладчиком.

YuS_2 18-03-2021 20:52 2953187

Цитата:

Цитата Андрей_Ахмедов@vk
1. увеличить рекурсию более 2 уровней в скрипте »

там нет такого ограничения.

Цитата:

Цитата Андрей_Ахмедов@vk
2. бороться с флагом "для чтения" который навешивается автоматом на входную и выходную папки »

Хмм, в планах такого не было... :)
Покажите скриншот - как именно, Вы проверяете атрибуты?

Цитата:

Цитата Андрей_Ахмедов@vk
3. вывести обработку ошибок ( скажем так ...... 1 - если нет тега "автор", "название" - оставлять как есть(ныне частенько так спешат верстать фб что их просто нет).... 2 - добавить цифровую составляющую к копиям, что бы не сносилось в ноль....3 - почему то некоторые зип не дают скрипту прочесть теги, только по распаковке) »

1. Посмотрю, как лучше сделать
2. С копиями тоже посмотрю...
3. Не понял про что речь. Архивы сначала распаковываются, а потом уже обрабатываются файлы *.fb2, никакие теги внутри архивов не парсятся.

YuS_2 19-03-2021 15:26 2953281

Андрей_Ахмедов@vk,
Цитата:

Цитата YuS_2
1. Посмотрю, как лучше сделать
2. С копиями тоже посмотрю... »

Как-то так:
Код:

param(
        [string]$in = '.\BOOKS',
        [string]$out = '.\BOOKS_OUT',
        [string[]]$include = ('*.fbz','*.zip'),
        # Каталог для книг .fb2, если какой-либо тег отсутствует
        # Для дальнейшего ручного разбора...
        [string]$error = '.\ERROR',
        # Путь к внешнему архиватору 7zip (консольному)
        [string]$zippath = 'd:\Program Files\7-Zip\7z.exe',
        # Ключ использования внешнего архиватора
        [switch]$extzip,
        # Ключ переименования распаковываемых файлов "имя файла_1",
        # если существуют, иначе будет вопрос на действие от архиватора
        # Работает только со внешним архиватором 7zip.
        [switch]$copy,
        # Ключ для удаления исходных архивов .zip и книг .fb2
        [switch]$delete
)
function expand-zip {
        process {
                try{
                        if ($_.extension -match '\.fbz|\.zip'){
                                if ($_.extension -eq '.fbz'){ren $_.fullname $($_.basename+'.zip')}
                                $zip = gi $($_.fullname -replace '\.fbz','.zip')
                                if ($extzip){
                                        $arg = " e $($zip.fullname)"
                                        if($zippath -match '7z.exe$'){
                                                pushd $zip.directoryname
                                                if ($copy){&$zippath 'e' $($zip.fullname) '-aou'}
                                                else {&$zippath 'e' $($zip.fullname)}
                                                popd
                                        } else {"Использовать необходимо 7z.exe"}
                                } else {expand-archive $zip.fullname $zip.directoryname -ea 1}
                                if($delete){del $zip}
                        }
                } catch {
                        popd
                        write-host "ошибка: $_" -for red
                }
        }
}
# https://docs.microsoft.com/ru-ru/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN
$except = '\[|\]|<|>|\*|\"|:|\?|\\|/|\|'
if (!(test-path $out -patht 'Container')){$null = md $out}
if (!(test-path $error -patht 'Container')){$null = md $error}
$folder = gi $out

dir $in -inc $include -file -rec|expand-zip

dir $in -inc '*.fb2' -file -rec|%{
        $arch,$b,$d,$d_author,$ser = $null,$null,$null,$null,$null
        if ((gc $_.fullname -tot 1) -match 'windows-1251'){
                if ($pscore = $psversiontable.psversion.major -gt 5){
                        $encoding = 'windows-1251'
                } else {$encoding = 'default'}
        } else {$encoding = 'utf8'}
        $book = ([xml](gc $_.fullname -enc $encoding)).fictionbook.description.'title-info'
        if(!(
                $book.author.'first-name' -and
                $book.author.'last-name' -and
                $book.'book-title'
        )){
                write-host "Заполните теги: author.'first-name',author.'last-name','book-title'" -for red
                write-host "файл - $($_.name)" -for red
                mi $_.fullname $error; return
        }
        $d = $folder.fullname+'\'+(
                (([array]$book.author)[0].'last-name'+' '+([array]$book.author)[0].'first-name') -replace $except
        )
        if(!(test-path $d -patht 'Container')){$d_author = md $d} else {$d_author = gi $d}
        if ($book.sequence.number){
                $b = $d_author.fullname+'\'+($book.sequence.name -replace ' ','-' -replace $except)
                if(!(test-path $b -patht 'Container')){$ser = md $b} else {$ser = gi $b}
                $new = $ser.fullname+'\'+$book.sequence.number+'_'+(
                        (($book.sequence.name -replace ' ','-')+'_'+$book.'book-title')  -replace $except
                )
        } else {
                $new = $d_author.fullname+'\'+($book.'book-title' -replace $except)
        }
        $tmp = $_
        try{mi $_.fullname $($new+$_.extension) -ea 1} catch {
                write-host "Невозможно переместить файл: $($tmp.fullname)" -for cyan
                write-host "Ошибка: $_" -for red
        }
        $arch = gi ($new+$_.extension)
        if ($extzip){
                if($zippath -match '7z.exe$'){
                        pushd $arch.directoryname
                        &$zippath 'a' -tzip $($arch.basename+'.zip') $($arch.name)
                        popd
                }
        } else {
                compress-archive $arch.fullname $($arch.directoryname+'\'+$arch.basename+'.zip')
        }
        if ($delete){del $arch}
}
dir $folder.fullname -filt '*.zip' -file -rec|ren -new {$_.basename+'.fbz'}

Дополнительно, к описанию выше:
Перемещает файлы без тегов в отдельный каталог, для ручного разбора...
Внедрен внешний архиватор 7zip, с возможностью оставлять копии исходных файлов...
Пример:
.\script.ps1 -ext -copy -del
- используется внешний архиватор
- файлы извлекаемые из архивов, будут переименованы (только с помощью внешнего архиватора), если одноименные файлы присутствуют в каталоге
- исходные файлы архивов и книг, будут удалены после обработки.

Андрей_Ахмедов@vk 19-03-2021 19:59 2953327

Спасибо. По работе старого скрипта ----

1 - немного разобрался... Так суть - не смотря на "- rec" (Recurse ? - все же сокращения пока для меня "лес темноватый, не везде проходимый") берется всего 2 уровня подкаталога. Ниже не просматривает.... Оттого и задавал вопрос

2- По " рид онли" - свойства папок из проводника.... Скрипт вывешивал (ошибку ) ред по удалению(исходник переносится в целевую для дальнейших действий скрипта и ошибка удаления) - проверял именно по этому, что бы разобраться по ошибке удаления файла перенесенного в целевой каталог\подкаталог - они так парой и существуют по окончанию работы старого скрипта... То есть *.fbz c *.fb2... Флаг снимал руками в свойствах папок, но как только запускал, он снова навешивался... Есть мысль что данное действие автоматом делает винда (точнее политика безопасности системы вкупе с защитником вондовс - своеобразная реакция на запуск скрипта без общего разрешения ... Запускал через батник скрипт, в pwsh и pwsh ise не делал разрешения )
(По этому поводу набросал себе блок схему на реализацию распаковки\запаковки в каталоге источника, с дальнейшим переносом в целевой... (ну надо же свои "наполеоновские" на будущее оформлять)) )

Цитата:

Цитата YuS_2
3. Не понял про что речь. Архивы сначала распаковываются, а потом уже обрабатываются файлы *.fb2, никакие теги внутри архивов не парсятся. »

3 - есть ньюанс из за которого почему то скрипт парсит fb2.zip тоже (...кстати некоторые fb2.zip имеют доступные теги фрикшен бук формата для чтения) , но так и не понял отчего так происходит. Источник - логи из (ошибок) редов.
....Хотя может и я внес - проба добавления флагов в командлеты скрипта.

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

Андрей_Ахмедов@vk 19-03-2021 20:20 2953330

Вот собственно блок схема которую хочу реализовать(если интересно)
черновая блок схема

0 выборка файлов fb2 и fb2.zip
1 если fb2.zip - распаковка
2 валидация fb2 ли это?
3 чтение хмл тегов автор, серия , название (создание массива для конкретного файла)
--- а. валидация на присутствие тегов (обработка ошибок)
--- 1 есть - переименование
--- 2 нет(пусты все) - сохранение текущего имени , оставляем как есть, заносим в файл лога(обработать.txt- типа такого)
имя данного файла
--- 3 стандартизация - убрать пробелы в имени (лишние, если присутствуют)--- часто бывает... (для примера --- Алексей Чижовский , (за ним каталог) Алексей Чижовский - лишние пробелы, лишние каталоги)) )
4 запаковка в зип
5 проверка каталога-получателя на существование подкаталога\ов для переноса
--- а. нет - создать по маске автор \ серия(если присутствует тег серии)
6 проверка на совпадение по имени (проверка на дубль)
--- а. есть - прибавка к имени количества файлов(уже существующих в подкаталоге))) .. как раз
номер текущего дубля выходит), занести в файл отчета .. типа дубликаты.txt
7 перенос готового файла
8 удаление исходника
9 каталог\ги пусты - удаление
--- почему в каталоге источника? - думаю что это будет скажем своеобразным "предохранителем" и не такая зависимость от флага "рид онли" в целевом каталоге, так как не понимаю точных причин данного действия системы
--- грубо конечно описано действо, но искать ПО для блок схем в момент написания... просто не мог(хотя помнится что встречалось такое на просторах интернета)
--- не везде где надо указаны обработчики ошибок, но думаю по прочтении это более-менее понятно из контекста

И спасибо за *.fbz - не всегда простые такие вот решения приходят в голову... Меня выручило это - читалка работает спокойно, а RAR и 7zip с ней не пересекаются))) и не надо мучаться с приоритетной привязкой по архивным расширениям.

YuS_2 19-03-2021 21:05 2953335

Цитата:

Цитата Андрей_Ахмедов@vk
не смотря на "- rec" (Recurse ? - все же сокращения пока для меня "лес темноватый, не везде проходимый") берется всего 2 уровня подкаталога. Ниже не просматривает »

Это странно. Никаких ограничений глубины вложенности рекурсии, в скрипте нет. Тут ничем помочь не могу...

Цитата:

Цитата Андрей_Ахмедов@vk
2- По " рид онли" - свойства папок из проводника »

Покажите скриншот свойств каталога.

Цитата:

Цитата Андрей_Ахмедов@vk
есть ньюанс из за которого почему то скрипт парсит fb2.zip тоже »

Ничего подобного скрипт "не умеет". Архив сначала должен быть распакован и только потом файл будет считан для обработки... это совсем разные форматы данных...

Цитата:

Цитата Андрей_Ахмедов@vk
Ну и по копиям - проще всего это при наличии подкаталога и имеющихся одноименных файлов по основной длине имени совпадающих »

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

Андрей_Ахмедов@vk 19-03-2021 21:21 2953337

Вложений: 1
Вот.
Предыстория - 11 марта как раз проверял))) единственно до снятия вручную стояло - для всех папок и файлов. То что видите сейчас на скрине - результат применения изначального скрипта на уже снятом перед этим флаге "только для чтения" вручную через то же диалоговое окно . Виндовс 8.1 про 64 бита

Андрей_Ахмедов@vk 19-03-2021 21:37 2953341

Цитата:

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

Нужны.
1. Эстетика - к примеру "битая" книга ... в которой картинка обложки была убита по разным причинам.
2. Переиздание дополненное той или иной информацией.
3. Как уже писал, просто банально пропущен номер тома в серии книг имя которых только номером тома и различить можно (есть серия типа "вархаммер" в которой названия идут таким вот образом ---
Костыль который стреляет. Том 1 (ну или Том первый, бывает номер римскими цифрами обозначен....)
....................................... Том 2 и т.д. (только вот в тегах номер тома пропущен - правил такое руками, но там было 40 томов в той серии....)
(название не конкретное "от балды" как говорится (там название "зубодробительное" на 30 знаков было типа хххххххххххххххххх.хххххххххх.Том(цифры латинские). fb2) - просто пока внешний диск с коллекцией отсутствует, брат попросил для переноса данных )
Руками можно конечно править такое, но когда объем 200Гб и встретится пару десятков таких серий.... настроение падает ниже уровня пола

Андрей_Ахмедов@vk 19-03-2021 21:52 2953344

Вложений: 1
Да и стандартизация (лишние пробелы) в самом массиве данных тега убрать можно автоматически? Имею в виду проверку на лишние пробелы в стринг переменной?
Скрин примера таких - 1 случай типичен, ниже .... думаю это уже в ручную править проще, чем нагружать скрипт сортировкой по не полному соответствию...

Андрей_Ахмедов@vk 20-03-2021 00:46 2953386

Или проще все же не на повершелл сделать... Тяжеловато пока воспринимается, не нашел начального уровня литературы еще.

YuS_2 20-03-2021 11:35 2953413

Цитата:

Цитата Андрей_Ахмедов@vk
Вот.
Предыстория - 11 марта как раз проверял))) единственно до снятия вручную стояло - для всех папок и файлов. То что видите сейчас на скрине - результат применения изначального скрипта на уже снятом перед этим флаге "только для чтения" вручную через то же диалоговое окно .»

Понятно. :)
Как и предполагал.
Это не флаг "только для чтения"... это микрософт, чудесным образом, впихнул в булевый чекбокс три состояния :)
"Птица", "Пусто", "Закрашено" - так вот, "птица" - это состояние "только для чтения", "закрашено" и "пусто" - нет.
Создайте каталог через проводник в любом месте и посмотрите его свойства, пощелкайте чекбокс - будет понятно о чем речь.

Цитата:

Цитата Андрей_Ахмедов@vk
Нужны. »

Цитата:

Цитата YuS_2
А вообще, нужны примеры таких копий... тогда можно и подумать над тем, как и куда их складировать... »

Цитата:

Цитата Андрей_Ахмедов@vk
в самом массиве данных тега убрать можно автоматически? Имею в виду проверку на лишние пробелы в стринг переменной?»

Это легко, только не в книге, а в наименовании, т.к. скрипт предназначен для обработки наименований. Надо было сделать сразу, да вот упустил этот момент. В следующей версии сделаю.

Цитата:

Цитата Андрей_Ахмедов@vk
Или проще все же не на повершелл сделать... »

Это только Вам решать. С наскока и за пару дней, точно изучить не получится.

YuS_2 20-03-2021 21:55 2953492

Андрей_Ахмедов@vk,
почти по Вашей блок-схеме :)
тестируйте:
script.ps1
Код:

<#
.SYNOPSIS
        Обработчик набора книг .fb2, для приведения структуры хранения в порядок

.Description
        Скрипт сканирует исходный каталог на наличие книг .fb2, а также архивов .zip,
        .fbz и .rar (rar - только для внешнего архиватора). Распаковывает архивы.
        Читает внутренние xml-теги и перименовывает файлы в соответствии с содержанием
        тегов. Создает структуру каталогов по авторам и наименованиям книг. Упаковывает
        целевые файлы fb2 в архивы fbz (zip). Удаляет исходные архивы, исходные и
        целевые файлы fb2, после упаковки последних в целевые архивы. Умеет создавать
        дубликаты с инкрементным счетчиком, при наличии в нескольких книгах
        совпадающих тегов. Исходные каталоги не удаляет.

.Parameter In
        Необязательный: Исходный каталог с книгами.

.Parameter Out
        Необязательный: Целевой каталог для создания структуры бибилиотеки.

.Parameter Include
        Необязательный: Фильтр для выборки архивов *.fbz, *.zip. Расширение *.rar
        указывать необязательно, при включении внешнего архиватора, оно будет
        добавлено автоматически.

.Parameter Error
        Необязательный: Целевой каталог для перемещения книг с отсутствующими тегами.

.Parameter Zipdelete
        Переключатель: Включает удаление исходных архивов.

.Parameter Fb2delete
        Переключатель: Включает удаление целевых файлов книг .fb2, после создания
        всех целевых архивов.

.Parameter Duble
        Переключатель: Включает возможность создания дубликатов книг, если теги,
        используемые для переименования книг, совпадают в нескольких книгах.

.Parameter log
        Переключатель: Включает ведение лога ошибок, возникающих в процессе работы.

.Parameter Errorlog
        Необязательный: Наименование файла лога ошибок.

.Parameter Extzip
        Переключатель: Включает использование внешнего архиватора. Скрипт настроен
        для использования архиватора 7zip. Если необходимо использование других
        архиваторов, то строки для обработки файлов, придется перенастроить.

.Parameter Zippath
        Необязательный: Путь к расположению исполняемого файла архиватора 7zip.

.Parameter Copy
        Переключатель: Включает автоматическое переименование файлов при извлечении
        из исходных архивов, если такие файлы уже существуют в каталоге. Если
        переключатель не указан, то лог распаковки вестись не будет (даже при
        включении параметра -Archlog) и все сообщения архиватора при распаковке
        будут выведены в консоль, для ручного управления при совпадении имен файлов.

.Parameter Archlog
        Переключатель: Включает ведение логов распаковки и упаковки файлов книг.

.Parameter 7zipexplog
        Необязательный: Наименование файла лога работы архиватора при распаковке.

.Parameter 7ziparclog
        Необязательный: Наименование файла лога работы архиватора при упаковке.

.Example
        .\script.ps1  -log -zipdel -duble -fb2del -ext -copy -archlog
       
        Включено ведение лога ошибок, удаление исх.архивов, удаление книг в целевом
        каталоге, вкл. создание дубликатов книг по наименованию, вкл. использование
        внешнего архиватора и ведение логов его работы. Копии с перименованием файлов,
        извлекаемых из исходных архивов, будут создаваться автоматически.
       
.Example
        .\script.ps1  -log -zipdel -duble -fb2del -ext -archlog

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

.Notes
        Created By YuS
        Version: 1.02
        Date: 21/03/2021
        Purpose/Change:        Переработана структура. Добавлены новые функции.

.Link
        http://forum.oszone.net/post-2953492.html#post2953492
#>
param(
        [string]$in = '.\BOOKS',
        [string]$out = '.\BOOKS_OUT',
        [string[]]$include = ('*.fbz','*.zip'),
        [string]$error = '.\ERROR',
        [switch]$zipdelete,
        [switch]$fb2delete,
        [switch]$duble,
        [switch]$log,
        [string]$errorlog = "$psscriptroot\error_log.txt",
        [switch]$extzip,
        [string]$zippath = 'd:\Program Files\7-Zip\7z.exe',
        [switch]$copy,
        [switch]$archlog,
        [string]$7zipexplog = "$psscriptroot\explog.txt",
        [string]$7ziparclog = "$psscriptroot\arclog.txt"
)
function expand-zip {
        param(
                [bool]$del,
                [bool]$external,
                [bool]$log,
                [bool]$excopy,
                [string]$filelog
        )
        process {
                try{
                        if ($_.extension -match '\.fbz|\.zip|\.rar'){
                                if ($_.extension -eq '.fbz'){ren $_.fullname $($_.basename+'.zip')}
                                $zip = gi $($_.fullname -replace '\.fbz','.zip')
                                if ($external){
                                        $arg = " e $($zip.fullname)"
                                        if($zippath -match '7z.exe$'){
                                                pushd $zip.directoryname
                                                if ($excopy){
                                                        if($log){
                                                                &$zippath 'e' $($zip.fullname) '-aou'|
                                                                out-file $filelog -enc utf8 -app
                                                        } else {&$zippath 'e' $($zip.fullname) '-aou'|out-null}
                                                } else {
                                                        &$zippath 'e' $($zip.fullname)
                                                }
                                                popd
                                        } else {"Использовать необходимо 7z.exe"}
                                } else {expand-archive $zip.fullname $zip.directoryname -ea 1}
                                if($del){del $zip}
                        }
                } catch {
                        popd
                        write-host "ошибка: $_" -for red
                }
        }
}
function fb2-arch {
        param(
                [io.fileinfo]$arch,
                [bool]$external,
                [bool]$log,
                [string]$filelog
        )
        process{
                if ($external){
                        if($zippath -match '7z.exe$'){
                                pushd $arch.directoryname
                                if($log){
                                        &$zippath 'a' -tzip -ur2x1y1z1w1 $($arch.basename+'.zip') $($arch.name)|
                                        out-file $filelog -enc utf8 -app
                                } else {&$zippath 'a' -tzip -ur2x1y1z1w1 $($arch.basename+'.zip') $($arch.name)|
                                out-null}
                                popd
                        }
                } else {
                        compress-archive $arch.fullname $($arch.directoryname+'\'+$arch.basename+'.zip')
                }
        }
}

function fb2-work {
        process{
                $tmp = $_
                $b_author_first,$b_author_second,$b_title,$seqname,$seqnum = $null,$null,$null,$null,$null
                $item,$b,$d,$d_author,$ser = $null,$null,$null,$null,$null
                if ((gc $_.fullname -tot 1) -match 'windows-1251'){
                        if ($pscore = $psversiontable.psversion.major -gt 5){
                                $encoding = 'windows-1251'
                        } else {$encoding = 'default'}
                } else {$encoding = 'utf8'}
                $book = ([xml](gc $_.fullname -enc $encoding)).fictionbook.description.'title-info'
                if(!(
                        $book.author.'first-name' -and
                        $book.author.'last-name' -and
                        $book.'book-title'
                )){
                        write-host "Заполните теги: author.'first-name',author.'last-name','book-title'" -for red
                        write-host "файл - $($_.name)" -for red
                        mi $_.fullname $error
                        if ($log){"Ошибка в тегах: $($error+'\'+$tmp.name)"|out-file $errorlog -enc 'utf8' -app}
                        return
                }
                $b_author_first = ([array]$book.author)[0].'first-name' -replace '(\s)\1+','$1' -replace
                '(^\s+|\s+$)' -replace $except
                $b_author_second = ([array]$book.author)[0].'last-name' -replace '(\s)\1+','$1' -replace
                '(^\s+|\s+$)' -replace $except
                $b_title = $book.'book-title' -replace '(\s)\1+','$1' -replace '(^\s+|\s+$)' -replace $except
                $d = $folder.fullname+'\'+$b_author_second+' '+$b_author_first
                if(!(test-path $d -patht 'Container')){$d_author = md $d} else {$d_author = gi $d}
                if ($book.sequence.name){
                        $seqname = $book.sequence.name -replace $except -replace '(\s)\1+','$1' -replace
                        '(^\s+|\s+$)' -replace ' ','-'
                        $seqnum = $book.sequence.number -replace '(\s)\1+','$1' -replace '(^\s+|\s+$)'
                        $b = $d_author.fullname+'\'+$seqname
                        if(!(test-path $b -patht 'Container')){$ser = md $b} else {$ser = gi $b}
                        $new = $ser.fullname+'\'+$seqnum+'_'+$seqname+'_'+$b_title
                } else {$new = $d_author.fullname+'\'+$b_title}
                try{mi $_.fullname $($new+$_.extension) -ea 1} catch {
                        write-host "Невозможно переместить файл: $($tmp.fullname)" -for cyan
                        write-host "Ошибка: $_" -for red
                        if ($log){"Ошибка в наименовании (дубликаты): исходный файл - $($tmp.fullname)"|
                        out-file $errorlog -enc 'utf8' -app}
                        if ($duble){
                                $cnt = (dir ($new+'*.fb2') -file).count
                                $new = $new + '_'+$cnt
                                mi $tmp.fullname $($new+$tmp.extension)
                                write-host Дубликат $($tmp.fullname) переименован и перемещён -for yellow
                                if ($log){"        - переименован и перемещен в библиотеку."|
                                out-file $errorlog -enc 'utf8' -app}
                        }
                }
                $item = gi ($new+$_.extension)
                fb2-arch $item -ext $extzip -log $archlog -file $7ziparclog
        }
}

# https://docs.microsoft.com/ru-ru/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN
$except = '\[|\]|<|>|\*|\"|:|\?|\\|/|\|'
if (!(test-path $out -patht 'Container')){$null = md $out}
if (!(test-path $error -patht 'Container')){$null = md $error}
if ($extzip){$include += '*.rar'}
$folder = gi $out

dir $in -inc $include -file -rec|
expand-zip -del $zipdelete -ext $extzip -log $archlog -file $7zipexplog -excopy $copy

dir $in -inc '*.fb2' -file -rec|fb2-work

dir $folder.fullname -filt '*.zip' -file -rec|ren -new {$_.basename+'.fbz'}
if ($fb2delete) {dir $folder.fullname -inc '*.fb2' -file -rec|del -rec -force}


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

Пример запуска:
Код:

.\script.ps1  -log -zipdel -duble -fb2del -ext -copy -archlog

Андрей_Ахмедов@vk 21-03-2021 13:01 2953537

По предыдущему скрипту ---

--- так сказать минусовка
1. fb2.zip - остаются в каталоге источнике(корневой и подкаталоги) , не запакованные в зип удалены (тут не все так однозначно - не все зип оригиналов остались... что то навевает о разных немного архиваторах и\ или запуска скрипта из батника .... странный эффект)
2. в корневом каталоге (book) остались простые fb2 файлы
3. в каталоге приемнике(book_out ) лежат парой fb2 & fb2.zip

--- плюсы
1 . глубина подкаталогов в 6 уровней спокойно проходится
2. меньше затраченного времени ( быстрее обработка происходит несколько)
.....................
Опять таки думается про запуск из батника - флаги "только чтение" навесились снова и в окне скрипта ред по поводу не возможности удаления
Через оболочку на прямую не запускал.
....................
Попробую еще вчерашний вариант.

YuS_2 21-03-2021 14:35 2953543

Цитата:

Цитата Андрей_Ахмедов@vk
1. fb2.zip - остаются в каталоге источнике(корневой и подкаталоги) , не запакованные в зип удалены (тут не все так однозначно - не все зип оригиналов остались... что то навевает о разных немного архиваторах и\ или запуска скрипта из батника .... странный эффект)
2. в корневом каталоге (book) остались простые fb2 файлы
3. в каталоге приемнике(book_out ) лежат парой fb2 & fb2.zip »

Читайте описание параметров (сегодня скрипт обновил, теперь он с описанием)... каждый ключ на что-то влияет.
В примерах есть строка запуска с описанием результатов.
В исходном каталоге могут, при определенном наборе ключей, оставаться файлы fb2, которые по какой-либо причине не были перенесены в целевой каталог (об этом будет запись в консоли и в логе, если включить ведение лога).

Цитата:

Цитата Андрей_Ахмедов@vk
1 . глубина подкаталогов в 6 уровней спокойно проходится »

никаких изменений в этой части не делалось.

Цитата:

Цитата Андрей_Ахмедов@vk
Опять таки думается про запуск из батника - флаги "только чтение" навесились снова и в окне скрипта ред по поводу не возможности удаления »

Это у Вас какие-то локальные проблемы. Про флаг "только для чтения", я писал выше... но запуск из cmd, я тоже проверил, ничего лишнего не происходит... в общем, проверьте систему.

Андрей_Ахмедов@vk 21-03-2021 17:14 2953565

Пытаюсь)))
Единственное что общего на данный момент это то что запускаю с батника.... думаю с этой стороны покопаться, но... в силу обстоятельств (завтра в больницу , под наблюдение ложиться надо ) чуть позже. На неделю точно...( ЭКГ вышла что то плохой, от слова совсем.)

Книгу Попова на телефоне помучаю - нашел чем оффлайн нормально сконвертировать в fb2, а то в pdf достаточно емкое было.
На VSC по повершелл кроме стандарта пока интересного не нашел, но подход больше нравится, нежели родного отладчика (ISE) .

Спасибо большое!
П.С. В любом случае я получил больше чем ожидал. Даже первым скриптом обработка данной массы книг уменьшалась раз в 8-10))) А на данном этапе это очень много рутинных операций (которые мелкие программы\плагины просто не воспринимали из за объема данных, да и не все каталогизаторы объективно воспринимали)
.....


Время: 10:27.

Время: 10:27.
© OSzone.net 2001-