• Теги этой статьи
  • Написание BAT файла для обработки архивов WinRAR с проверкой целостности

    В этой статье я буду писать BAT файл для групповой перепаковки RAR архивов в архивы нового формата WinRAR 5 и параллельной проверке их целостности.

    Начну с описания поставленной задачи. Есть набор файлов, RAR архивы с какой-то информацией, в моём случае с книгами. Эти файлы все лежат в одной папке и имеют последовательную нумерацию. Последовательная нумерация не важна, главное что все файлы имеют расширение файла RAR. Вот примерный список:

    archive_1.rar
    archive_2.rar
    archive_3.rar
    .............
    archive_n.rar

    Мне надо перебрать все эти архивы и сделать с ними некоторые действия:

    1. Протестировать архивный файл;
    2. Если файл без повреждений, то распаковать его в папку;
    3. Добавить в эту папку файл с сылкой на сайт (URL-файл);
    4. Если в архиве есть вложенный архив, то и его распаковать в папку;
    5. Упаковать содержимое папки обратно в RAR архив.

    Параллельно буду создавать файл с списком поврёждённых архивов (назову его CorruptedFiles.txt), чтобы знать над чем работать вручную. В папку с архивными файлами я положу необходимые для обработки файлы: Rar.exe, WinRAR.exe и созданный Books.url.

    BAT файл для распаковки архивов

    Сперва создам файл Extract.bat для тестирования и распаковки архивов:

    @echo off
    setlocal EnableDelayedExpansion
    if exist "log.txt" del "log.txt" >> log.txt
    if exist "CorruptedFiles.txt" del "CorruptedFiles.txt" >> log.txt
    echo ############### DeCompress Files ###############
    FOR %%R IN (*.rar) DO (
      echo %%~nR
      WinRAR t -ibck -inul "%%R" >> log.txt
      If !ERRORLEVEL!==0 (
        WinRAR x -ad -ibck "%%R" *.* >> log.txt
        cd %%~nR
        FOR %%F IN (*.rar,*.zip,*.7z) DO (
          echo %%~nF
          ..\WinRAR t -ibck -inul "%%F" >> log.txt
          If !ERRORLEVEL!==0 (
            ..\WinRAR x -ad -ibck "%%F" *.* "%%~pF\" >> ..\log.txt
            if exist "%%F" del "%%F" >> ..\log.txt
          ) ELSE (
            echo %%R > %%F [Error = !ERRORLEVEL!] >> CorruptedFiles.txt
            echo #-----> Error in file %%R > %%F
            if exist "%%R" ren "%%R" "%%~nR.rar_bad" >> log.txt
          )
        )
        cd ..
        if exist "%%~nR\Books.url" del "%%~nR\Books.url" >> log.txt
        if exist "%%~nR" copy "Books.url" "%%~nR\Books.url" >> log.txt
        if exist "%%R" del "%%R" >> log.txt
      ) ELSE (
        echo %%R [Error = !ERRORLEVEL!] >> CorruptedFiles.txt
        echo #-----> Error in file %%R
        if exist "%%R" ren "%%R" "%%~nR.rar_bad" >> log.txt
      )
    )

    Упаковываем папки с информацией в архивы

    Теперь напишу файл Pack.bat для упаковки папок в архивы WinRAR 5:

    @echo off
    setlocal EnableDelayedExpansion
    if exist "log.txt" del "log.txt" >> log.txt
    echo ############### Compress Files ###############
    FOR /d %%a in (*) DO (
      echo %%a
      if exist "%%a.rar" del "%%a.rar" >> log.txt
      winrar a -y -r -ep1 -inul -ibck -ri1 -s -m5 -ma5 -md32MB "%%a.rar" "%%a\" >> log.txt
      if exist "%%a" rmdir /Q /S "%%a"
    )

    BAT файл для процесса перепаковки

    В итоге, объединив эти два файла, получаю один файл RePack.bat :

    @echo off
    setlocal EnableDelayedExpansion
    if exist "log.txt" del "log.txt" >> log.txt
    if exist "CorruptedFiles.txt" del "CorruptedFiles.txt" >> log.txt
    echo ############### DeCompress Files ###############
    FOR %%R IN (*.rar) DO (
      echo %%~nR
      WinRAR t -ibck -inul "%%R" >> log.txt
      If !ERRORLEVEL!==0 (
        WinRAR x -ad -ibck "%%R" *.* >> log.txt
        cd %%~nR
        FOR %%F IN (*.rar,*.zip,*.7z) DO (
          echo %%~nF
          ..\WinRAR t -ibck -inul "%%F" >> log.txt
          If !ERRORLEVEL!==0 (
            ..\WinRAR x -ad -ibck "%%F" *.* "%%~pF\" >> ..\log.txt
            if exist "%%F" del "%%F" >> ..\log.txt
          ) ELSE (
            echo %%R > %%F [Error = !ERRORLEVEL!] >> CorruptedFiles.txt
            echo #-----> Error in file %%R > %%F
            if exist "%%R" ren "%%R" "%%~nR.rar_bad" >> log.txt
          )
        )
        cd ..
        if exist "%%~nR\Books.url" del "%%~nR\Books.url" >> log.txt
        if exist "%%~nR" copy "Books.url" "%%~nR\Books.url" >> log.txt
        if exist "%%R" del "%%R" >> log.txt
      ) ELSE (
        echo %%R [Error = !ERRORLEVEL!] >> CorruptedFiles.txt
        echo #-----> Error in file %%R
        if exist "%%R" ren "%%R" "%%~nR.rar_bad" >> log.txt
      )
    )
    echo ############### Compress Files ###############
    FOR /d %%a in (*) DO (
      echo %%a
      if exist "%%a.rar" del "%%a.rar" >> log.txt
      winrar a -y -r -ep1 -inul -ibck -ri1 -s -m5 -ma5 -md32MB "%%a.rar" "%%a\" >> log.txt
      if exist "%%a" rmdir /Q /S "%%a"
    )

    Всё, помещаем в одну папку все наши файлы архивов. Туда же копируем Rar.exe, WinRAR.exe, Books.url и созданный RePack.bat. Запускаем RePack.bat и наблюдаем процесс перепаковки.

    Примечание: Для успешного завершения процесса перепаковки необходимо убедиться в наличии свободного места на диске! :)

    По окончании процесса просматриваем файл CorruptedFiles.txt на предмет повреждённых архивов.

    День второй. Оптимизация BAT файла для перепаковки архивов

    Ещё вчера, когда я начал применять в действии файл перепаковки RePack.bat, я заметил, что приходится очень долго ждать. Сразу заметил, что я выполняю лишнии операции: тестирую архив, потом его распаковываю, произвожу такие двойные операции со всеми архивами и получаю в итоге множество папок с данными, которые потом упаковываю в новые архивы. Согласитесь, не очень оптимальное решение. Лучшим вариантом было бы сразу без тестирования архивов их распаковывать, а в случае ошибки - пропускать. И второе, надо бы, для экономии места на диске, распакованный архив сразу же запаковывать обратно, тем самым не держать на диске всю информацию из тысяч папок. Получается, что надо распаковать архив в папку и тут же, если не было ошибок, запаковать обратно эту папку в архив. Итак, что же у меня получилось после оптимизации BAT файла перепаковки архивов:

    @echo off
    setlocal EnableDelayedExpansion
    if exist "log.txt" del "log.txt" >> log.txt
    if exist "CorruptedFiles.txt" del "CorruptedFiles.txt" >> log.txt
    echo ############### RePack Files ###############
    FOR %%R IN (*.rar) DO (
      SET MyError=0
      echo %%~nR - Decompress
      WinRAR x -ad -ibck -inul "%%R" *.* >> log.txt
      If !ERRORLEVEL!==0 (
        cd %%~nR
        FOR %%F IN (*.rar,*.zip,*.7z) DO (
          echo %%~nF
          ..\WinRAR x -ad -ibck -inul "%%F" *.* "%%~pF\" >> ..\log.txt
          If !ERRORLEVEL!==0 (
            if exist "%%F" del "%%F" >> ..\log.txt
          ) ELSE (
            SET MyError=2
            echo %%R\%%F [Error = !ERRORLEVEL!] >> ..\CorruptedFiles.txt
            echo %%R\%%F - Error in file
          )
        )
        cd ..
        if exist "%%~nR\Books.url" del "%%~nR\Books.url" >> log.txt
        if exist "%%~nR" copy "Books.url" "%%~nR\Books.url" >> log.txt
      ) ELSE (
        SET MyError=1
        echo %%R [Error = !ERRORLEVEL!] >> CorruptedFiles.txt
        echo %%R - Error in file
      )
      If !MyError!==0 (
        if exist "%%R" del "%%R" >> log.txt
        echo %%~nR - Compress
        winrar a -y -r -ep1 -inul -ibck -ri1 -s -m5 -ma5 -md32MB "%%R" "%%~nR\" >> log.txt
        if exist "%%~nR" rmdir /Q /S "%%~nR" >> log.txt
      ) ELSE (
        echo MyError = !MyError!
        if exist "%%~nR.rar" ren "%%~nR.rar" "%%~nR.rar_bad" >> log.txt
        if exist "%%~nR" rmdir /Q /S "%%~nR" >> log.txt
      )
    )

    День третий. Дальнейшая оптимизация BAT файла для перепаковки архивов

    По результатам второго дня написания командного файла для перепаковки архивов была выявлена такая особенность архиватора WinRAR: все файлы архивов с книгами (текстовые файлы TXT, PDF, FB2 и т.д.) упакованные в формате WinRAR 5 имели чуть меньшую степень сжатия - архивы были больше в объеме. Нехорошо, подумал я и начал искать причину. Причина была найдена. Оказывается, что предыдущие версии WinRAR 4.xx имели возможность указать принудительно в параметрах -mc<par> специальные параметры сжатия для текстовых и аудио файлов. В документации к WinRAR написано следующее: "Сжатие текста позволяет улучшить коэффициент сжатия для простых текстовых данных, но его сжатие и скорость декомпрессия также как способность использовать несколько ядер процессоров гораздо хуже, чем в общем алгоритме сжатия. Таким образом, состояние по умолчанию для этой опции "отключено". Вы можете изменить его на "Auto", чтобы позволить WinRAR выбрать этот алгоритм автоматически для подходящих данных. "Force" применяет алгоритм сжатия текста ко всем данным, но будьте готовы к замедлению архивирования и извлечения при использовании этой опции."

    Вот и получается, что мелкие текстовые файлы лучше сжимаются в формате WinRAR 4 с параметрами: -md4M -mc12:128t, но при этом будет хуже скорость упаковки, однако результирующий файл архива будет меньше по объёму.

    В конечном итоге я решил, что буду определять объём старого архива и принимать решение с какими параметрами упаковывать самые маленькие файлы (до 1MB), средние файлы (от 1 до 5MB) или большие файлы (более 5MB). Cамые маленькие файлы упаковываю с параметрами: -m5 -ma4 -md1M -mc4:64t, средние файлы упаковываю с параметрами: -m5 -ma4 -md4M -mc12:128t и большие файлы -m5 -ma5 -md32M

    Итак, на третий день у меня получилась следующая оптимизация BAT файла для перепаковки архивов:

    @echo off
    setlocal EnableDelayedExpansion
    if exist "CorruptedFiles.txt" del "CorruptedFiles.txt"
    echo ################## RePack Files ##################
    FOR %%R IN (*.rar) DO (
      SET MyError=0
      echo %%~nR - Decompress file
      WinRAR x -ad -ibck -inul "%%R" *.*
      If !ERRORLEVEL!==0 (
        cd %%~nR
        FOR %%F IN (*.rar,*.zip,*.7z) DO (
          echo %%~nF
          ..\WinRAR x -ad -ibck -inul "%%F" *.* "%%~pF\"
          If !ERRORLEVEL!==0 (
            If exist "%%F" del "%%F"
          ) ELSE (
            SET MyError=2
            echo %%R\%%F [Error = !ERRORLEVEL!] >> ..\CorruptedFiles.txt
            echo %%R\%%F - Error #!MyError! in file
          )
        )
        cd ..
        if exist "%%~nR\Books.url" del "%%~nR\Books.url"
        if exist "%%~nR" copy "Books.url" "%%~nR\Books.url" > nul
      ) ELSE (
        SET MyError=1
        echo %%R [Error = !ERRORLEVEL!] >> CorruptedFiles.txt
        echo %%R - Error #!MyError! in file
      )
      If !MyError!==0 (
        if %%~zR LEQ 1000000 (
          set ArchParam=-m5 -ma4 -md1M -mc4:64t
        )
        if %%~zR GTR 1000000 (
          if %%~zR LEQ 5000000 (
            set ArchParam=-m5 -ma4 -md4M -mc12:128t
          )
        )
        if %%~zR GTR 5000000 (
          set ArchParam=-m5 -ma5 -md32M
        )
        if exist "%%R" del "%%R"
        echo %%~nR - Compress file
        winrar a -y -r -ep1 -inul -ibck -ri1 -s !ArchParam! "%%R" "%%~nR\"
        if exist "%%~nR" rmdir /Q /S "%%~nR"
      ) ELSE (
        if exist "%%~nR.rar" ren "%%~nR.rar" "%%~nR.rar_bad"
        if exist "%%~nR" rmdir /Q /S "%%~nR"
      )
    )

    Компьютерный мир

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

    Частичное или полное использование материалов сайта разрешается только при условии добавления ссылки на непосредственный адрес материала на нашем сайте.