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

18/04/2019
6.0 K

В этой статье я буду писать 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"
  )
)

Launch the License Manager from the bin folder (by default “C:/Program Files (x86)/Embarcadero/Studio/23.0/bin/LicenseManager.exe“) and delete any trial or beta (Test Field) license that you...

Карта разрушений и жертв российской агрессии в городе Мариуполь, на карте отмечены более 2000 пострадавших домов. На карте отмечены не только фото домов, но свидетельства их жителей, а так же место боевых...

Из-за военных событий 2014 года в Донецке тренер по плаванию Алексей Снежко и его жена вынужденно переехали в Киев. А теперь, в 2022-м, 33-летний Алексей потерял обоих родителей в Мариуполе. Как пережить...

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

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

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