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

时间:2015-07-03 05:48:05

标签: windows batch-file

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

test1  : 2
test1\test11 :3
newfolder : 5
newfolder : 10
像这样。

1 个答案:

答案 0 :(得分:4)

robocopy "x:\target\folder" "x:\target\folder" /l /nocopy /is /e /nfl /njh /njs

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

这只会调用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
    )

这将使用for /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

这将

  • 对于起始目录(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="
        )
    )

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

代码将在此列表上迭代(for /f %%a)。找到文件夹行(它包含反斜杠并且可以由for /f %%b拆分)时,文件夹名称将保存在变量中。当相应的页脚行被引导时(它没有被反斜杠分割),该行被分割以获得文件数(for /f %%d),文件夹名称和文件数被回显到控制台(此处延迟)需要扩展来检索变量内容,因为它们是在同一个循环中设置的)

注意:使用for /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"
    )

已修改以适应评论: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%