windows批处理嵌套for循环和变量

问题描述 投票:0回答:1

我一直在编写一个批处理脚本来对我存储在电脑上的约 7tb 的翻录媒体进行编目。虽然大部分脚本都有效,但我一直停留在自动确定文件夹是否包含电视节目或电影的部分。该函数的工作原理是通过获取根文件夹的名称(例如 Die_Hard)为每个类别(电影与电视)分配一个权重值,处理可能存在于其中的任何子文件夹的名称,并吐出一个值,然后主程序将其转换电视为 T,电影为 M,以及置信度分数。我遇到的问题是该函数无法正确解析关键字,并将电视节目标记为电影,反之亦然。如果我手动进行计算,效果很好,但我通常为 Bash 编写脚本,而且我不太明白这里不起作用。

:DETERMINE
    setlocal EnableDelayedExpansion
    REM DT NAME
    set "DTNM=%~1"
    echo %DTNM%
    REM DT Location
    set "DLOC=%~2"
    REM echo %DLOC%
    REM DT Score
    set /A dtq=0
    REM DT Movie Weight
    set /A DTMV=0
    REM DT TV Weight
    set /A DTTV=0
    REM DT TV Keywords
    set "DTTR=Season,90;Volume,70;TV,45;S1,100;V1,75;"
    REM DT Movie Keywords
    set "DMVT=%DTNM%,45;Theatrical,90;Extended,60;Unrated,60;Extra,5;Bonus,10;Bonus-Content,15;Bonus-Disc,12;Bonus-Disk,12;Bonus_Content,15;Bonus_Disc,12;Bonus_Disk,12;Bonus Content,15;Bonus Disc,12;Bonus Disk,12;Special,2;Special-Features,18;Special-Content,15;Special_Features,18;Special_Content,15;Special Features,18;Special Content,15;"
    REM DMTV Calculator
    REM Iterate through subfolders
    for /f "tokens=*" %%U in ('dir /b /ad "%DLOC%"') do (
        REM Iterate through Keyword list
        for /f "tokens=* delims=;" %%V in ("%DMVT%") do (
            REM Split Keyword from weight
            REM echo %%V
            for /f "tokens=1-2 delims=," %%W in ("%%V") do (
                echo %%U|find /I "%%X" >nul
                if errorlevel 0 ( @set /A DMTV=!DMTV! + %%X )
                REM echo %%U %%W %%X
            echo 1
            )
        )
        REM DMTV escapw workaround
        set DMTV=!DMTV!
    )
    REM DTTV Calculator
    REM Iterate through subfolders
    for /f "tokens=*" %%T in ('dir /b /ad "%DLOC%"') do (
        REM Iterate through keyword list
        for /f "tokens=* delims=;" %%S in ("%DTTR%") do (
            REM split keyword from weight
            for /f "tokens=1-2 delims=," %%Q in ("%%S") do (
                echo %%T|find /I "%%R" >nul
                REM echo %%T %%Q %%R
                if errorlevel 0 ( @set /A DTTV=!DTTV! + %%R )
            )
        )
        REM DMTV escapw workaround
        set DTTV=!DTTV!
    )
    echo %DMTV% %DTTV%
    
    set /A DEQ=%DMTV% - %DTTV%
    echo %DEQ%
    ENDLOCAL
    GOTO:EOF

仅供参考,电视节目的子文件夹是季/卷号(例如 S1、S2),而电影则直接位于根文件夹下,但系列和三部曲除外,其子文件夹与根文件夹,但也有指示电影的数字。

脚本应该为电影输出正数,为电视节目输出负数。数字离 0 越远,置信度分数就越高。我有一个脚本版本,它使用 20 多个嵌套的 If 语句,但无法添加新关键字,有时会输出不正确的数字。我尝试以不同的方式解析关键字,甚至使用两个字符串,一个用于关键字,一个用于随附的评级。如果这是 bash,我可以使用数组,但据我所知,这是不可能的。

该函数的输出应如下所示:

45
(对于电影或系列电影)或
-100
对于电视节目。

主程序解析输出后,它看起来像这样:

Discs
   Airplane - 2 Movies - 100% (90) [1080/XX GB]
   ...
   JOHN WICK - 4 Movies - 100% (180) [UHD/XX GB]
   ...
   The Office - 9 Seasons - 100% (-900) [NTSC/XX GB]
   ...

但是目前,子程序的输出如下所示:

外壳窗口:

...
Airplane
Missing operator.
1
Missing operator.
1
Missing operator.
Missing operator.
90 180
-90
...

主程序输出:

   Airplane - 90 Seasons - 90% (-90) [1080/XX GB]
loops batch-file iteration
1个回答
0
投票

我暂时休息了一下……但我想通了。 现在它会输出每个类别的正确权重。

setlocal EnableDelayedExpansion
REM DT NAME
set "DTNM=%~1"
REM DT Location
set "DLOC=%~2"
set DDBG=0
if %DDBG% EQU 1 ( echo # ---%DTNM% & echo # %DLOC%)
REM DT Score
set /A dtq=0
REM DT Movie Weight
set /A DTMV=10
REM DT TV Weight
set /A DTTV=0
REM DT TV Keywords
set "DTTR=Season,90;Volume,70;TV,45;^S[0123456789][0123456789],100;^S[0123456789],100;^V[0123456789][0123456789],75;"
REM DT Movie Keywords
set "DMVT=%DTNM%,45;^[0123456789],10;Theatrical,90;Extended,60;Unrated,60;Extra,5;Bonus,10;Bonus-Content,15;Bonus-Disc,12;Bonus-Disk,12;Bonus_Content,15;Bonus_Disc,12;Bonus_Disk,12;Bonus Content,15;Bonus Disc,12;Bonus Disk,12;Special,2;Special-Features,18;Special-Content,15;Special_Features,18;Special_Content,15;Special Features,18;Special Content,15;"
set DMTC=0
set DMMC=0
REM DMTV Calculator
REM Iterate through subfolders
for /f "tokens=* delims=" %%U in ('dir /b /ad "%DLOC%"') do (
    REM Iterate through Keyword list
    for %%V in ("%DMVT:;=" "%") do (
        REM Split Keyword from weight
        REM echo %%V
        for /f "tokens=1-2 delims=," %%W in (%%V) do (
            REM echo %%U
            REM echo | set /p= is equivalent to echo -n
            if %DDBG% EQU 1 (echo | set /p=# "TITLE" %%U "TOKEN" %%W "WEIGHT" %%X)
            echo %%U|findstr /R /I /M "%%W" >nul
            if !errorlevel!==0 ( @set /A DMTV=!DMTV! + %%X & if %DDBG% EQU 1 (echo  "Match")) else (if %DDBG% EQU 1 (echo  "No Match"))
            REM echo %%U %%W %%X
        REM echo 1
        set /A DMMC+=1
        )
    )
REM DMTV escapw workaround
set DMTV=!DMTV!
)
REM DTTV Calculator
REM Iterate through subfolders
for /f "tokens=*" %%U in ('dir /b /ad "%DLOC%"') do (
    REM Iterate through keyword list
    for %%V in ("%DTTR:;=" "%") do (
        REM split keyword from weight
        for /f "tokens=1-2 delims=," %%W in (%%V) do (
            REM echo | set /p= is equivalent to echo -n
            if %DDBG% EQU 1 (echo | set /p=# "TITLE" %%U "TOKEN" %%W "WEIGHT" %%X)
            echo %%U|findstr /R /I /M "%%W" >nul
            REM echo %%T %%Q %%R
            if !errorlevel!==0 ( @set /A DTTV=!DTTV! + %%X & if %DDBG% EQU 1 (echo  "Match")) else (if %DDBG% EQU 1 (echo  "No Match"))
        set /A DMTC+=1
        )
    )
REM DMTV escapw workaround
set DTTV=!DTTV!
)
REM empty movie score workaround (adds one to movie in case score is null or 0)
set /A DMTV+=1
if %DDBG% EQU 1 (echo # "MOV ITR" !DMMC! "TV ITR" !DMTC! "MOV SCR" %DMTV% "TV SCR" -%DTTV%)

set /A DEQ=%DMTV% - %DTTV%
if %DDBG% EQU 1 (echo %DEQ%)
set U=
ENDLOCAL & set "DEQ=%DEQ%"
GOTO:EOF

以下是我修复的内容的摘要:

  • 我用
    Find
    替换了
    FindStr
    。通过使用
    FindStr
    我获得了使用正则表达式的能力。这允许检测文件夹名称中的数字。
  • FindStr
    输出 3 个错误条件。
    0
    表示成功,
    1
    表示不匹配,
    2
    表示失败。这意味着
    if errorlevel 0
    是这种情况下的正确用法。此外,当启用
    if errorlevel 0
    时,
    if !errorlevel!==0
    相当于
    DelayedExpansion
  • 两个计算部分现在使用相同的变量。我原本以为这会导致问题,但当
    for
    语句生成大量令牌时,使用不同的变量实际上会导致更多问题。
  • for
    的情况下,我必须使用标准的
    for %%V in ("%DTTR:;=" "%")
    循环,因为它是 not 循环遍历目录,并且我不希望每个令牌都获得自己的变量。我需要它一次解析一个标记并且只使用一个变量,在这种情况下
    %%V
  • 我在
    %%X
    中使用
    %%W
    而不是
    FindStr
    。这意味着它正在搜索权重而不是关键字。
  • 我添加了一个调试模式,这样我就可以禁用打印输出,因为这是一个子例程,最终的程序不需要此部分的输出。
  • 我给
    DMTV
    (电影计算的最终值)加1,因为当指定目录中没有文件夹时
    DMTV
    被清除。
© www.soinside.com 2019 - 2024. All rights reserved.