如果文件夹名称包含Unicode字符,批处理无法正常工作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果文件夹名称包含Unicode字符,批处理无法正常工作相关的知识,希望对你有一定的参考价值。

以前,我被要求创建以下批次。

How can I extract multiple archives to each folder with WinRAR command line?

我认为它工作正常,但当文件夹名称包含Unicode字符(❤,㉓等)时,文件夹中的压缩文件从未解压缩。因此,即使它们包含在文件夹名称中,如何提取Unicode字符?

另一个问题是,如果文件夹中没有压缩文件(zip,rar,partX.rar),则以下批处理不会移动到done文件夹。即使文件夹中没有压缩文件,我也希望每次都移动到done文件夹。

之前:

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%System32findstr.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%WinRARWinRAR.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%System32findstr.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%System32choice.exe /C NY /N /T 2 /D N /M "Break execution [N/Y]? "
        %PromptForBreak% if errorlevel 2 goto EndBatch
    )
)

:EndBatch
endlocal
答案

在Windows 8或更新的Windows版本上,默认情况下将Consolas设置为控制台窗口的字体,以下批处理文件应该可以工作:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

for /F "tokens=2 delims=:" %%I in ('%SystemRoot%System32chcp.com') do set "CodePage=%%I"
%SystemRoot%System32chcp.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%System32findstr.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%WinRARWinRAR.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%System32findstr.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%System32choice.exe /C NY /N /T 2 /D N /M "Break execution [N/Y]? "
        %PromptForBreak% if errorlevel 2 goto EndBatch
    )
)

:EndBatch
if defined CodePage %SystemRoot%System32chcp.com %CodePage%
endlocal

此批处理文件与先前询问的文件夹移动相反。所有文件夹都移动到子文件夹done,而不仅仅是那些成功提取存档文件的文件夹。存档文件提取错误的子文件夹保留在源文件夹中,就像以前的版本一样。

在Windows 7上默认配置光栅字体,它是终端,不支持UTF-8。这导致在执行批处理文件期间显示:

系统无法写入指定的设备。

原因由eryksun分析一次,可以在下面的评论中阅读Using another language (code page) in a batch file made for others的回答。

通过从批处理文件中删除该行可以避免错误消息:

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

即使在cmd.exe输出此错误消息时,归档文件提取任务和文件夹移动仍由Windows 7上的批处理文件完成。

在Windows XP上默认配置了Raster Fonts,它也是不支持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%System32findstr.exe /L /C:"<DIR>" ^| %SystemRoot%System32findstr /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%WinRARWinRAR.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%System32findstr.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%System32choice.exe /C NY /N /T 2 /D N /M "Break execution [N/Y]? "
        %PromptForBreak% if errorlevel 2 goto EndBatch
    )
)

:EndBatch
endlocal

缺点是移动的目录在子目录done中最后是短8.3目录名而不是原始目录名。

以上是关于如果文件夹名称包含Unicode字符,批处理无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

PHP Pear Mail 无法发送带有 Unicode 字符的名称

关于爬取数据保存到json文件,中文是unicode解决方式

linux变量里有特殊字符脚本会对其处理吗

通过 Windows 批处理文件将字符串替换为文本文件中的 unicode

使用 JDBC 处理包含 Unicode(旁遮普语、印地语)数据和表/列名称的 Access 数据库

在Windows上的python 2.7中列出具有Unicode名称的文件