Пакет не работает правильно, если имя папки содержит символы Юникода - PullRequest
0 голосов
/ 23 апреля 2019

Ранее меня просили создать следующий пакет.

Как извлечь несколько архивов в каждую папку с помощью командной строки WinRAR?

Я думал, что это былоработает нормально, но когда имя папки содержит символы Unicode (❤, ㉓ и т. д.), сжатый файл в папке никогда не распаковывается.Следовательно, как извлечь символы Unicode, даже если они включены в имя папки?

В качестве еще одной проблемы следующий пакет не перемещается в готовую папку, если нет сжатых файлов (zip, rar, partX)..rar) в папке.Даже если в папке нет сжатых файлов, я хочу каждый раз переходить в готовую папку.

До:

C:
│
└─test
    ├─AAAA
    │      XXXX.rar
    │      XXXX.jpg
    │
    ├─㉓
    │      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
    │  │
    │  ├─㉓
    │  │      XXXX.doc
    │  │      XXXX.jpg
    │  │
    │  ├─DDDD
    │  │      XXXX.doc
    │  │      XXXX.jpg
    │  │
    │  └─EEEE
    │         XXXX.jpg
    │
    └─CCCC(error_file)
           XXXX.rar
           XXXX.jpg

@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

1 Ответ

1 голос
/ 24 апреля 2019

В Windows 8 или более новой версии Windows с Consolas , установленным по умолчанию в качестве шрифта для консольных окон, должен работать следующий пакетный файл:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

for /F "tokens=2 delims=:" %%I in ('%SystemRoot%\System32\chcp.com') do set "CodePage=%%I"
%SystemRoot%\System32\chcp.com 65001 2>nul

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 "NoFolderMove="
    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 "NoFolderMove=1"
                set "ArchiveFile=%SourceFolder%\%%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 "%SourceFolder%\%%I\%%J" ) else for %%# in ("%%~nJ") do del /F /Q "%SourceFolder%\%%I\%%~n#.part*%%~xJ"
            )
        )
    )
    if not defined NoFolderMove (
        md "%SourceFolder%\done" 2>nul
        if exist "%SourceFolder%\done\" move /Y "%SourceFolder%\%%I" "%SourceFolder%\done\" >nul
        %PromptForBreak% %SystemRoot%\System32\choice.exe /C NY /N /T 2 /D N /M "Break execution [N/Y]? "
        %PromptForBreak% if errorlevel 2 goto EndBatch
    )
)

:EndBatch
if defined CodePage %SystemRoot%\System32\chcp.com %CodePage%
endlocal

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

В Windows 7 по умолчанию настроено Растровые шрифты , что Терминал , что неподдержка UTF-8.Это приводит к отображению во время выполнения командного файла:

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

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

Сообщение об ошибке можно избежать, удалив из пакетного файластрока:

echo Extracting "%SourceFolder%\%%I\%%J" ...

Задача извлечения архивного файла и перемещение папки, тем не менее, выполняется пакетным файлом в Windows 7 даже при выводе этого сообщения об ошибке cmd.exe.

В WindowsXP по умолчанию настроен также Растровые шрифты , который также Terminal не поддерживает UTF-8.Но в Windows XP командный процессор Windows останавливает выполнение командного файла после четвертой строки.Таким образом, этот пакетный файл нельзя использовать в Windows XP, по крайней мере, без изменения шрифта в свойствах процесса, выполняющего этот пакетный файл.

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

@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=| tokens=4" %%I in ('dir "%SourceFolder%\*" /AD-H /ON /X 2^>nul ^| %SystemRoot%\System32\findstr.exe /L /C:"<DIR>" ^| %SystemRoot%\System32\findstr /I /E /L /V /C:" done" /C:" ." /C:" .."') do (
    set "NoFolderMove="
    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 "NoFolderMove=1"
                set "ArchiveFile=%SourceFolder%\%%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 "%SourceFolder%\%%I\%%J" ) else for %%# in ("%%~nJ") do del /F /Q "%SourceFolder%\%%I\%%~n#.part*%%~xJ"
            )
        )
    )
    if not defined NoFolderMove (
        md "%SourceFolder%\done" 2>nul
        if exist "%SourceFolder%\done\" move /Y "%SourceFolder%\%%I" "%SourceFolder%\done\" >nul
        %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

Недостатком является то, что перемещенные каталоги имеют в подкаталоге done, наконец, короткие 8.3 имен каталогов, а не исходные имена каталогов.

...