如何使用WinRAR命令行将多个档案提取到每个文件夹? [英] How can I extract multiple archives to each folder with WinRAR command line?

查看:140
本文介绍了如何使用WinRAR命令行将多个档案提取到每个文件夹?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在命令行中将每个文件夹中存在的ZIP和RAR存档提取到相应的文件夹中.此外,我只想在解压缩过程中没有错误的情况下删除原始压缩文件.如果解压缩档案时出现错误,则应将档案文件名写入错误日志文件,并且提取过程应继续下一个档案文件.

I want to extract ZIP and RAR archives existing in each folder to the respective folder at the command line. Furthermore, I want to delete the original compressed file only if there is no error during decompression. If there is an error on extracting an archive, the archive file name should be written to an error log file and extraction process should continue with the next archive file(s).

我想在解压缩成功后将每个文件夹移动到done文件夹.但是批处理文件不应移动不包含任何存档文件的文件夹.

I want to move every folder to done folder after the decompression is successful. But folders not containing any archive file should not be moved by the batch file.

之前:

C:
│
└─test
    ├─AAAA
    │      XXXX.rar
    │      XXXX.jpg
    │
    ├─BBBB
    │      XXXX.zip
    │      XXXX.jpg
    │
    ├─CCCC(error_file)
    │      XXXX.rar
    │      XXXX.jpg
    │
    ├─DDDD
    │      XXXX.part1.rar
    │      XXXX.part2.rar
    │      XXXX.jpg
    │
    └─EEEE
           XXXX.jpg

之后:

C:
│
└─test
    ├─done
    │  │
    │  │
    │  ├─AAAA
    │  │      XXXX.doc
    │  │      XXXX.jpg
    │  │
    │  ├─BBBB
    │  │      XXXX.doc
    │  │      XXXX.jpg
    │  │
    │  └─DDDD
    │         XXXX.doc
    │         XXXX.jpg
    │
    ├─CCCC(error_file)
    │      XXXX.rar
    │      XXXX.jpg
    │
    └─EEEE
           XXXX.jpg


下面的代码是从Mofi从问题的初始版本中得到的答案,并由我改编而成的.

The following code taken from Mofi's answer from initial version of the question and adapted by me did not work.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFolder=C:\test"
set "LogExtract=%SourceFolder%\ExtractionLog.txt"
set "LogError=%SourceFolder%\ErrorLog.txt"
set "ArchiveExtracted="

del /Q "%LogExtract%" "%LogError%" 2>nul

for /D %%I in ("%SourceFolder%\*") do (
    if /I not "%%~nxI" == "done" (
        for /F "eol=| delims=" %%J in ('dir "%%I\*.rar" "%%I\*.zip" /A-D-H /B /ON 2^>nul') do (
            if exist "%%I\%%J" (
                echo Extracting "%%I\%%J" ...
                "%ProgramFiles%\WinRAR\WinRAR.exe" x -cfg- -logpfu="%LogExtract%" -or -- "%%I\%%J" "%%I\"
                if errorlevel 1 (
                    set "ArchiveFile=%%I\%%J"
                    >>"%LogError%" call echo Error %%ErrorLevel%% on extracting "%%ArchiveFile%%"
                ) else (
                    echo %%~nJ| %SystemRoot%\System32\findstr.exe /I /R "\.part[0123456789][0123456789]*$" >nul
                    if errorlevel 1 ( del /F "%%I\%%J" ) else for %%# in ("%%~nJ") do del /F /Q "%%I\%%~n#.part*%%~xJ"
                )
            )
        )
        if /I not "%%~nxI" == "done" if not exist "%%I\*.rar" if not exist "%%I\*.zip" move /Y "%%I" "%SourceFolder%\done\"
    )
)


endlocal

推荐答案

Rar.exe仅支持 WinRAR 的程序文件文件夹中其手册Rar.txt顶部所记录的RAR存档. WinRAR.exe支持创建RAR和ZIP存档以及提取多种存档类型.因此,在下面的批处理文件代码中使用WinRAR.exe.

Rar.exe supports only RAR archives as documented at top of its manual Rar.txt in program files folder of WinRAR. WinRAR.exe supports creation of RAR and ZIP archives and extraction of multiple archive types. Therefore WinRAR.exe is used in batch file code below.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFolder=C:\Test"
set "LogExtract=%SourceFolder%\ExtractionLog.txt"
set "LogError=%SourceFolder%\ErrorLog.txt"
set "ArchiveExtracted="

del /Q "%LogExtract%" "%LogError%" 2>nul

for /D %%I in ("%SourceFolder%\*") do (
    if /I not "%%~nxI" == "done" (
        for %%J in ("%%I\*.rar" "%%I\*.zip") do (
            if exist "%%J" (
                echo Extracting "%%J" ...
                "%ProgramFiles%\WinRAR\WinRAR.exe" x -cfg- -ibck -logpfu="%LogExtract%" -o+ -y -- "%%J" "%%I\"
                if errorlevel 1 (
                    set "ArchiveFile=%%J"
                    >>"%LogError%" call echo Error %%ErrorLevel%% on extracting "%%ArchiveFile%%"
                ) else (
                    set "#%%~nxI=%%I"
                    set "ArchiveExtracted=1"
                    echo %%~nJ| %SystemRoot%\System32\findstr.exe /I /R "\.part[0123456789][0123456789]*$" >nul
                    if errorlevel 1 ( del /F "%%J" ) else for %%# in ("%%~nJ") do del /F /Q "%%I\%%~n#.part*%%~xJ"
                )
            )
        )
    )
)

if defined ArchiveExtracted (
    md "%SourceFolder%\done" 2>nul
    if exist "%SourceFolder%\done\" (
        for /F "tokens=2 delims==" %%I in ('set #') do move /Y "%%I" "%SourceFolder%\done\"
    )
)

endlocal

定义父源文件夹并从以前的执行中删除可能已经存在的日志文件后,外部 FOR 会在指定的源文件夹中搜索未隐藏的子目录.

After definition of parent source folder and deletion of perhaps already existing log files from a previous execution the outer FOR searches in specified source folder for non-hidden subdirectories.

对于每个找到的子目录(名称为done的子目录除外),内部 FOR 会在子目录中搜索未隐藏的* .rar和* .zip文件,并执行WinRAR.exe来提取找到的每个子目录存档文件到子目录中.

For each found subdirectory except the one with name done the inner FOR searches for non-hidden *.rar and *.zip files in the subdirectory and executes WinRAR.exe to extract each found archive file into the subdirectory.

WinRAR 提取每个存档文件

  • 保持目录结构,
  • 忽略标准配置,
  • 在后台,这意味着最小化了系统托盘,
  • 将从 RAR 存档中提取的文件记录到Unicode编码(无BOM的UTF-16 Little Endian)提取日志文件中,
  • 覆盖所有现有文件,
  • 假设所有查询(如出现错误)为.
  • with keeping directory structure,
  • with ignoring standard configuration,
  • in background which means minimized to system tray,
  • with logging extracted files from RAR archives to Unicode encoded (UTF-16 Little Endian without BOM) extraction log file,
  • with overwriting all files already existing,
  • with assuming yes for all queries like on an error.

WinRAR 自动提取多卷存档的所有卷.

WinRAR automatically extracts all volumes of a multi-volume archive.

WinRAR 的错误值更大或等于 1退出,该错误在帮助页面上的 WinRAR 帮助中记录WinRAR退出代码列表.

WinRAR exits with a value greater or equal 1 on an error as documented in help of WinRAR on help page List of WinRAR exit codes.

如果未成功提取由 WinRAR 退出且值为0并指示错误消息的归档文件,则归档文件名将分配给环境变量ArchiveFile输出行,将 WinRAR 的退出代码和文件名写入错误日志文件.错误日志文件的编码取决于Windows命令处理器在启动批处理文件处理时定义的字符编码和代码页.

The archive file name is assigned to environment variable ArchiveFile in case of a not 100% successful extraction of an archive file indicated by exit of WinRAR with value 0 and next an error message line is output writing exit code of WinRAR and the file name into the error log file. The error log file is encoded depending on character encoding and code page defined by Windows command processor on starting batch file processing.

由于在执行外部 FOR 所有%%之前,Windows命令处理器已在解析整个命令块时已替换了环境变量ErrorLevelArchiveFile,因此在每侧均用两个百分号引用只是%.在执行 ECHO 之前,命令 CALL 导致对 ECHO 命令行的第二次解析,从而导致用该环境的当前值替换%Errorlevel%变量以及%ArchiveFile%的当前存档文件名.

The environment variables ErrorLevel and ArchiveFile are referenced with two percent signs on each side because of Windows command processor replaces already on parsing entire command block before executing outer FOR all %% by just %. The command CALL results in a second parsing of the ECHO command line before executing ECHO which results in replacing %Errorlevel% by current value of this environment variable as well as %ArchiveFile% by current archive file name.

echo Error %ErrorLevel% on extracting "%ArchiveFile%"这样的 ECHO 行,没有命令 CALL ,将导致在外部 FOR <前用环境变量ErrorLevel的当前值替换%ErrorLevel%./strong>完全执行,这意味着用0并将%ArchiveFile%替换为空字符串,这当然无济于事.

An ECHO line like echo Error %ErrorLevel% on extracting "%ArchiveFile%" without command CALL would result in replacing %ErrorLevel% by current value of environment variable ErrorLevel before outer FOR is executed at all which means with 0 and would replace %ArchiveFile% by an empty string which of course would not be helpful.

将存档文件名分配给环境变量ArchiveFile,并像ErrorLevel一样引用,以处理正确的Archive%20!Important!.rar之类的文件名.

The archive file name is assigned to environment variable ArchiveFile and referenced like ErrorLevel to handle also a file name like Archive%20!Important!.rar correct.

在多卷归档文件上出现错误时,不会删除任何RAR归档文件部分,从而导致提取多卷归档文件的所有卷多次,并且将多卷归档文件的每个部分都写入错误日志中.文件.

On an error on a multi-volume archive none of the RAR archive parts are deleted resulting in the approach of extracting all volumes of the multi-volume archive multiple times with each part of multi-volume archive file written into the error log file.

在成功提取单个归档文件时删除归档文件,或者在成功提取多卷归档文件时删除多卷归档文件的所有部分.此外,还设置了一个环境变量,其中#加上子目录名称作为环境变量名称,并将子目录的完整路径作为值,以记住哪些子目录包含至少一个成功提取的存档以供以后移动.对于这种简单的方法,要求子目录名称中都不能包含等号.

The archive file is deleted on a successful extraction of a single archive file respectively all parts of a multi-volume archive are deleted on successful extraction of a multi-volume archive. Additionally an environment variable is set with # plus subdirectory name as environment variable name and full path of subdirectory as value to remember which subdirectories contained at least one successfully extracted archive to move it later. It is required for this simple method that no subdirectory name contains an equal sign.

以上代码无法在子目录中多个* .rar或* .zip文件中的FAT32或ExFAT驱动器上使用.在这种情况下,有必要在由 FOR 执行的命令 DIR 中使用以%ComSpec% /C开头的单独命令进程,并在后台捕获输出归档文件名.然后,内部的 FOR 运行时,将列出由于删除FAT32和ExFAT驱动器上的存档文件而导致在循环迭代期间未修改的存档文件名称的列表.

The above code could not work on FAT32 or ExFAT drives on more than one *.rar or *.zip file in a subdirectory. In this case it is necessary to use command DIR executed by FOR in a separate command process started with %ComSpec% /C in background and capture the output archive file names. Then the inner FOR runs with a list of archive file names not modified during the loop iterations as caused by deletion of the archive files on FAT32 and ExFAT drives.

如果归档文件本身包含* .rar或* .zip文件,并且上面的批处理代码可能会偶然提取该文件,则也需要此备用批处理文件.

This alternate batch file is also needed if an archive file contains itself *.rar or *.zip files which should not be extracted by chance as it can happen with the batch file code above.

因此,第二个批处理代码比第一个更安全.

So this second batch code is more safe than the first one.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFolder=C:\Test"
set "LogExtract=%SourceFolder%\ExtractionLog.txt"
set "LogError=%SourceFolder%\ErrorLog.txt"
set "ArchiveExtracted="

del /Q "%LogExtract%" "%LogError%" 2>nul

for /D %%I in ("%SourceFolder%\*") do (
    if /I not "%%~nxI" == "done" (
        for /F "eol=| delims=" %%J in ('dir "%%I\*.rar" "%%I\*.zip" /A-D-H /B /ON 2^>nul') do (
            if exist "%%I\%%J" (
                echo Extracting "%%I\%%J" ...
                "%ProgramFiles%\WinRAR\WinRAR.exe" x -cfg- -ibck -logpfu="%LogExtract%" -o+ -y -- "%%I\%%J" "%%I\"
                if errorlevel 1 (
                    set "ArchiveFile=%%I\%%J"
                    >>"%LogError%" call echo Error %%ErrorLevel%% on extracting "%%ArchiveFile%%"
                ) else (
                    set "#%%~nxI=%%I"
                    set "ArchiveExtracted=1"
                    echo %%~nJ| %SystemRoot%\System32\findstr.exe /I /R "\.part[0123456789][0123456789]*$" >nul
                    if errorlevel 1 ( del /F "%%I\%%J" ) else for %%# in ("%%~nJ") do del /F /Q "%%I\%%~n#.part*%%~xJ"
                )
            )
        )
    )
)

if defined ArchiveExtracted (
    md "%SourceFolder%\done" 2>nul
    if exist "%SourceFolder%\done\" (
        for /F "tokens=2 delims==" %%I in ('set #') do move /Y "%%I" "%SourceFolder%\done\"
    )
)

endlocal

注意: WinRAR 版本5.70不支持将 ZIP 存档中提取文件的文件名写入提取日志文件.帮助页面 Switch -LOG [fmt] [= name]-将名称写入日志文件中.

Note: WinRAR version 5.70 does not support writing the file names of extracted files from ZIP archives to the extraction log file. This is documented at top of help page Switch -LOG[fmt][=name] - write names to log file.

最后,如果已成功提取然后删除了任何存档,则批处理文件会将存在以#开头的环境变量的所有文件夹移动到父源目录的子目录done中.因此,无法成功提取至少一个归档文件的子目录将在文件夹移动时被忽略,而没有归档文件的子目录也将被忽略.如果最终目标目录不是父源目录的子目录,则代码可能会更容易.

Finally, if any archive was successfully extracted and then deleted, the batch file moves all folders for which an environment variable starting with # exists into subdirectory done in parent source directory. So subdirectories with no successful extraction of at least one archive are ignored on folder movement as well as subdirectories which have no archive file. The code could be easier if the final destination directory is not a subdirectory of the parent source directory.

另一个变种,可在完成档案提取后立即移动文件夹.在这种情况下,有必要使用捕获的子目录名称列表,因为在外部 FOR 循环的循环迭代过程中,子目录的列表会发生变化. FINDSTR 用于从子目录名称列表中过滤出文件夹done.

One more variant which moves a folder immediately after archive extraction(s) finished. It is necessary in this case to work with a captured list of subdirectory names as the list of subdirectories changes during loop iterations of outer FOR loop. FINDSTR is used to filter out folder done from list of subdirectory names.

此批处理文件等待用户选择,以在两秒钟后自动选择 n o来中断执行.因此,批处理作业可以被用户安全地中断.可以通过使用参数/noprompt启动批处理文件来避免出现此提示.

This batch file waits for a user choice to break execution with choosing no automatically after two seconds. So the batch job can be safely broken by a user. This prompt can be avoided by starting the batch file with parameter /noprompt.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "PromptForBreak="
if /I "%~1" == "/noprompt" set "PromptForBreak=rem"

set "SourceFolder=C:\Test"
set "LogExtract=%SourceFolder%\ExtractionLog.txt"
set "LogError=%SourceFolder%\ErrorLog.txt"

del /Q "%LogExtract%" "%LogError%" 2>nul

for /F "eol=| delims=" %%I in ('dir "%SourceFolder%\*" /AD-H /B /ON 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /L /V /X /C:done') do (
    set "ArchiveExtracted="
    for /F "eol=| delims=" %%J in ('dir "%SourceFolder%\%%I\*.rar" "%SourceFolder%\%%I\*.zip" /A-D-H /B /ON 2^>nul') do (
        if exist "%SourceFolder%\%%I\%%J" (
            echo Extracting "%SourceFolder%\%%I\%%J" ...
            "%ProgramFiles%\WinRAR\WinRAR.exe" x -cfg- -ibck -logpfu="%LogExtract%" -o+ -y -- "%SourceFolder%\%%I\%%J" "%SourceFolder%\%%I\"
            if errorlevel 1 (
                set "ArchiveFile=%SourceFolder%\%%I\%%J"
                >>"%LogError%" call echo Error %%ErrorLevel%% on extracting "%%ArchiveFile%%"
            ) else (
                set "ArchiveExtracted=1"
                echo %%~nJ| %SystemRoot%\System32\findstr.exe /I /R "\.part[0123456789][0123456789]*$" >nul
                if errorlevel 1 ( del /F "%SourceFolder%\%%I\%%J" ) else for %%# in ("%%~nJ") do del /F /Q "%SourceFolder%\%%I\%%~n#.part*%%~xJ"
            )
        )
    )
    if defined ArchiveExtracted (
        md "%SourceFolder%\done" 2>nul
        if exist "%SourceFolder%\done\" move /Y "%SourceFolder%\%%I" "%SourceFolder%\done\"
        %PromptForBreak% %SystemRoot%\System32\choice.exe /C NY /N /T 2 /D N /M "Break execution [N/Y]? "
        %PromptForBreak% if errorlevel 2 goto EndBatch
    )
)

:EndBatch
endlocal

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /?
  • del /?
  • dir /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • if /?
  • md /?
  • move /?
  • set /?
  • setlocal /?
  • call /?
  • del /?
  • dir /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • if /?
  • md /?
  • move /?
  • set /?
  • setlocal /?

这篇关于如何使用WinRAR命令行将多个档案提取到每个文件夹?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆