批处理文件计算文件夹和子文件夹文件中的所有文件,并使用批处理文件在文件夹名称中写入输出文件

Vit*_*ala 0 windows batch-file

如何计算文件夹和子文件夹文件中的文件。文件夹名称和文件数以及子文件夹名称和文件数。前任:

test1  : 2
test1\test11 :3
newfolder : 5
newfolder : 10
Run Code Online (Sandbox Code Playgroud)

像这样。

MC *_* ND 6

robocopy "x:\target\folder" "x:\target\folder" /l /nocopy /is /e /nfl /njh /njs
Run Code Online (Sandbox Code Playgroud)

或者

pushd "x:\target\folder" && (
    robocopy . . /l /nocopy /is /e /nfl /njh /njs
    popd
)
Run Code Online (Sandbox Code Playgroud)

这将简单地调用robocopy,但我们不会复制任何内容,而是要求不复制任何内容,只返回应处理内容的列表 ( /nocopy /l)。我们要求从当前文件夹(先前的复制pushd命令时)到当前文件夹,包括在处理相同的文件(/is),处理空的子文件夹(/e,以包括与0的文件夹),但仅处理两个电平(/lev:2当前文件夹和下面的一个),不生成文件列表 ( /nfl),没有作业标题 ( /njh) 和没有作业摘要 ( /njs)

结果将是相同的列表,但具有文件夹名称和更改列中的文件数

保持原始输出格式

@echo off
    setlocal enableextensions disabledelayedexpansion

    pushd "x:\target\folder" && (
        for /f "tokens=1,*" %%a in ('
            robocopy . . /l /nocopy /is /e /nfl /njh /njs
        ') do echo %%~fb : %%a
        popd
    )
Run Code Online (Sandbox Code Playgroud)

这将使用 afor /f处理前一个robocopy命令,将行拆分为两个标记,第一个将包含文件数并存储在 中%%a,第二个包含行的其余部分并将存储在%%b. 对于内部robocopy命令输出中的每一行,do执行子句中的代码:只需 echo 以相反的顺序控制台两个标记。

如果robocopy不能使用(比 Vista 旧的操作系统),则

@echo off
    setlocal enableextensions disabledelayedexpansion

    for /d /r "x:\target\folder" %%a in (*) do for /f "tokens=1,5" %%b in ('
        dir /a-d "%%~fa.\*" 2^> nul ^| findstr /b /c:"  " ^|^| echo 0
    ') do if "%%c"=="" echo %%~fa : %%b
Run Code Online (Sandbox Code Playgroud)

这会

  • 对于开始目录 ( for /r /d)下的每个文件夹,获取一个引用并将其存储在%%a可替换参数中
  • dir使用文件夹的完整路径运行命令%%~fa
  • 使用管道 ( |) 过滤列表以仅检索以两个空格开头的行(页脚行)
  • 如果未找到任何行(即dir命令失败),则输出 0
  • 生成的行由命令dir | findstr处理for /f。我们将读取第一个标记(在适当的行中的文件数)和第五个(仅存在于带有目录信息的页脚行中)
  • 如果第五个元素是空的,这一行有关于文件的信息,而不是文件夹,所以,回显文件夹路径和里面的文件
  • 最后,恢复之前的活动目录

这种方法的问题dir | findstr是对每个子文件夹执行。这将使这比robocopy解决方案慢。

它可以更快,但需要更多的代码

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "root=%cd%"

    set "folder="
    for %%r in ("%root%") do (
        set "rootDrive=%%~dr\" 
        if not defined rootDrive set "rootDrive=\\"
        for /f "delims=" %%a in ('
            dir /s /a "%%~fr.\*" 2^>nul ^| findstr /r /c:"^  " /c:"^ .*\\."
        ') do for /f "tokens=1,* delims=\" %%b in ("%%~a") do if not "%%c"=="" (
            set "folder=%%c"
        ) else if defined folder (
            for /f %%d in ("%%~a") do (
                setlocal enabledelayedexpansion
                echo(!rootDrive!!folder! : %%d
                endlocal
            )
            set "folder="
        )
    )
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们将只执行一个dir命令来检索完整列表并使用列表过滤findstr以仅检索具有文件夹名称和每个文件夹页脚的行。

代码将for /f %%a在此列表上迭代 ( )。当找到一个文件夹行(它包含一个反斜杠并且可以用 分隔for /f %%b)时,文件夹名称保存在一个变量中。当读取到对应的footer行时(没有被反斜杠分割),分割行得到文件for /f %%d数(变量内容,因为它们被设置在同一个循环中)

注意:使用 afor /f处理通过执行命令生成的大量数据列表可能非常慢(命令处理内存的方式存在不良行为)。对于这种情况,有必要首先执行生成数据的命令(dir | findstr在这种情况下)将其输出发送到文件,然后使用for /f来处理文件。

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "root=%~1"
    if not defined root for %%a in (.) do set "root=%%~fa"

    set "folder="
    for %%t in ("%temp%\%~nx0.%random%%random%.tmp") do for %%r in ("%root%") do (

        set "rootDrive=%%~dr\" 
        if not defined rootDrive set "rootDrive=\\"

        ( dir /s /a "%%~fr.\*" 2^> nul | findstr /r /c:"^  " /c:"^ .*\\." ) > "%%~ft"

        for /f "usebackq delims=" %%a in ("%%~ft") do (
            for /f "tokens=1,* delims=\" %%b in ("%%~a") do if not "%%c"=="" (
                set "folder=%%c"
            ) else if defined folder (
                for /f %%d in ("%%~a") do (
                    setlocal enabledelayedexpansion
                    echo(!rootDrive!!folder! : %%d
                    endlocal
                )
                set "folder="
            )
        )

        del /q "%%~ft"
    )
Run Code Online (Sandbox Code Playgroud)

编辑以适应评论:robocopy解决方案更改为包括文件总数

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "total=0"
    pushd "x:\target\folder" && (
        for /f "tokens=1,*" %%a in ('
            robocopy . . /l /nocopy /is /e /nfl /njh /njs
        ') do (
            echo %%~fb : %%a
            set /a "total+=%%a"
        )
        popd
    )
    echo Total files: %total%
Run Code Online (Sandbox Code Playgroud)