【问题标题】:Windows Batch - Variable Substitution Not Working in Inner For Loop eg filesizeWindows 批处理 - 变量替换在内部 For 循环中不起作用,例如文件大小
【发布时间】:2021-02-04 00:20:35
【问题描述】:

到目前为止,我已经创建了 2 个 Windows 批处理文件(1 个使用 forfiles,另一个使用 for)在 4 个远程文件路径的目录树中查找所有 0 字节文件,但是它们需要 2.5 小时以上,因为它们接近62,000 个文件和 31 个子目录。

我正在尝试使用带有 dir 的嵌套 for 循环创建第三个版本,但变量替换在内部 for 循环中不起作用。

请知道为什么会出现这种情况以及如何解决它?

我还需要在父目录中包含文件,但目前不包含它们。

主要使用 Windows Server 2008 R2。

Windows 批处理:

@ECHO OFF

@REM Variables
SET my_parent_dir=c:\temp
SET my_dir=""

@REM Loop through sub-dirs (excludes parent dir but need to include it)
FOR /F "usebackq delims=" %%D IN (`"DIR %my_parent_dir% /AD/B/S"`) DO (

    ECHO dir: %%D
    SET my_dir=%%D

    CALL :inner_loop
)
exit /b

:inner_loop
    echo inner dir: = %my_dir%
    
    @REM Loop through files in my_dir directory, sorted by filesize
    FOR /F "delims=" %%F IN ('DIR %my_dir% /A-D/B/OS 2^>nul') DO (

        @REM Variable substitution is NOT working in the inner loop
        ECHO filename+size+datetime: %%F    %%~zF   %%~tF
        
        @REM If filesize > 0 bytes, break out of inner loop
        @REM NOT WORKING as variable substitution not working
        @REM IF %%~zF GTR 0 (
            @REM echo BREAK***
            @REM exit /b
        @REM )

    )
exit /b

输出(注意:没有文件大小和日期时间):

C:\Temp>list_files_02c.bat
dir: c:\temp\old_1
inner dir: = c:\temp\old_1
filename+size+datetime: old_1_file_3.cmd
filename+size+datetime: old_1_file_1.txt
filename+size+datetime: old_1_file_2.txt
dir: c:\temp\old_2
inner dir: = c:\temp\old_2
filename+size+datetime: old_2_file_2.log
filename+size+datetime: old_2_file_5.txt
filename+size+datetime: old_2_file_3.log
filename+size+datetime: old_2_file_1.cmd
filename+size+datetime: old_2_file_4.txt
dir: c:\temp\old_3
inner dir: = c:\temp\old_3
filename+size+datetime: old_3_file_4.cmd
filename+size+datetime: old_3_file_2.log
filename+size+datetime: old_3_file_3.cmd
filename+size+datetime: old_3_file_1.txt
C:\Temp>

更新 - 解决方案: 现在让它工作(也适用于远程路径),谢谢大家。

解决方案 Windows 批处理:

@ECHO OFF

@REM Save current directory. Required when PushD & PopD are used for remote paths.
SETLOCAL

@REM Variables
@REM SET "my_parent_dir=\\my_pc_name\c$\temp"
SET "my_parent_dir=c:\temp"
SET "my_dir=%my_parent_dir%"

@REM Loop through parent directory files
CALL :inner_loop

@REM Loop through subdirectories (excludes parent directory)
FOR /F "delims=" %%D IN ('DIR "%my_parent_dir%" /B /AD /S') DO (

    ECHO dir %%D
    SET "my_dir=%%D"

    @REM Loop through subdirectory files
    @REM Required so can break out of inner loop but remain in outer loop
    CALL :inner_loop
)
GOTO :end_script


:inner_loop
    ECHO inner dir = %my_dir%
    
    @REM Change to my_dir directory, so variable substitution will work
    PushD "%my_dir%" && (
    
        @REM Loop through files in my_dir directory, sorted by file size, smallest first
        FOR /F "delims=" %%F IN ('DIR /B /A-D /OS 2^>nul') DO (

            @REM If filesize > 0 bytes, break out of inner loop
            IF %%~zF GTR 0 (
                PopD
                EXIT /b
            )

            ECHO filename+size+datetime: %%F    %%~zF   %%~tF

        )
        
    ) & PopD


:end_script
    @REM Return to current directory. Required when PushD & PopD are used for remote paths.
    ENDLOCAL

    ECHO Finished

解决方案输出:

C:\Temp>list_files_02c.bat
inner dir = c:\temp
filename+size+datetime: blank_file2.txt 0       07/10/2020 12:12 PM
filename+size+datetime: blank_file1.txt 0       07/10/2020 12:12 PM
dir c:\temp\old_1
inner dir = c:\temp\old_1
filename+size+datetime: old_1_file_3.txt        0       07/10/2020 01:19 PM
dir c:\temp\old_2
inner dir = c:\temp\old_2
filename+size+datetime: old_2_file_2.txt        0       07/10/2020 01:19 PM
filename+size+datetime: old_2_file_5.txt        0       07/10/2020 01:19 PM
dir c:\temp\old_3
inner dir = c:\temp\old_3
filename+size+datetime: old_3_file_4.txt        0       07/10/2020 01:19 PM
Finished

C:\Temp>

【问题讨论】:

  • 内部循环没有按预期工作,因为 DIR 输出由分配给环境变量 my_dir 的字符串定义的目录中的文件,而没有文件路径。因此 FOR 在启动批处理文件时设置的当前目录中搜索 DIR 输出的文件,但在当前目录中找不到它们。因此,FOR 无法确定存储在与当前目录不同的目录中的文件的文件大小。我也推荐阅读this answer,尤其是Issue章节。
  • 啊,非常感谢莫菲

标签: windows loops batch-file nested


【解决方案1】:

只需在目录中使用pushdpopd 即可。作为旁注,请在变量和值的两侧用双引号括起来,如SET "my_parent_dir=c:\temp"

@ECHO OFF

@REM Variables
SET "my_parent_dir=c:\temp"
SET "my_dir="      REM You value should be between = and "

@REM Loop through sub-dirs (excludes parent dir but need to include it)
FOR /F "delims=" %%D IN ('DIR "%my_parent_dir%" /B /AD /S') DO (

    ECHO dir: %%D
    SET my_dir=%%D

    CALL :inner_loop
)
exit /b

:inner_loop
    echo inner dir: = %my_dir%
    pushd "%my_dir%"
    @REM Loop through files in my_dir directory, sorted by filesize
    FOR /F "delims=" %%F IN ('DIR /B /A-D /OS 2^>nul') DO (

        @REM Variable substitution is NOT working in the inner loop
        ECHO filename+size+datetime: %%F    %%~zF   %%~tF
        
        @REM If filesize > 0 bytes, break out of inner loop
        @REM IF %%~zF GTR 0 (
            @REM echo BREAK***
            @REM exit /b
        @REM )

    )
    popd
exit /b

PS!!我从第一个 for 循环中删除了反引号和 usebackq,因为它不是必需的。

【讨论】:

  • 我曾考虑过,因为我在另一个脚本中使用 pushd 和 popd 并带有访问远程路径的循环,所以我想我需要在这里执行此操作,谢谢。
  • 一些小的调整让它适用于远程路径,再次感谢 Gerhard。将我的工作代码添加到我的原始帖子中,因为太长而无法在此评论中发布。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多