【问题标题】:Batch Count .txt Files and echoing filenames after function based on count批量计数 .txt 文件和基于计数的函数后回显文件名
【发布时间】:2016-03-18 17:04:08
【问题描述】:

我有一个工作批处理脚本,它计算目录树(包括子目录)中的 .txt 文件,然后如果计数 GTR 大于 2,则基本上通知用户他们必须在再次运行此脚本之前执行某些操作。

我希望脚本在通知用户时也告诉他们 txt 文件的文件名。

这就是我所拥有的。

下面会检查根文件夹和所有子目录中的 .txt 文件。 这会计算 .txt 文件的数量并设置它。

@echo off & Setlocal
:: Search for files in the Tree
Set "sFolder=C:\folder\folder\root"
Set "sFileType=txt"
set "i=0"

PushD "%sFolder%" &&(
  FOR /R "." %%i IN (*) DO ( If /i "%%~xi"==".%sFileType%" ( set /a i+=1 ) ) )

如果计数大于 3,则转到通知用户(这是简单的回显命令)

If %i% GTR 2 goto NotifyUser

我没有得到的是如何将 3 个或更多找到的 .txt 文件名回显给用户。我知道这将是一个变量,但我似乎无法弄清楚以及如何将其放入上述命令中。

另外.. 在回显中,有时文件名可能有一个“.”而不是扩展名

IE:文件名.txt.gpg

上面的 count 命令不会将示例文件名计为 .txt 文件... 但是取决于命令的名称回显可能会认为这是一个 txt 文件..我不希望上面的文件名示例作为计数的 txt 文件之一回显给用户(因为它不被计数)。 (希望这是有道理的)。

【问题讨论】:

  • 你可以让for /R循环已经对*.txt文件进行过滤,而不是枚举所有文件(*);所以不需要if /I 语句。而不是pushd [...] && (for /R [...]) 我会使用pushd [...] && ((for /R [...]) & popd)...

标签: variables batch-file count


【解决方案1】:

您可能不想多次扫描 .txt 文件,因此最简单的解决方案是将文件列表存储在临时文件中,当且仅当行数更多时才输入结果比 2. 可以使用 FIND 统计行数,使用 FOR /F 捕获统计结果。

@echo off
setlocal
set "root=C:\folder\folder\root"
set "out=%temp%\myTextFileList.txt"
dir /b /s /a-d "%root%\*.txt" >"%out%"
for /f %%N in ('find /c /v "" <"%out%"') do if %%N gtr 2 (
  echo You cannot proceed because you have more than 2 .TXT files:
  type "%out%"
  del "%out%"
  pause
  exit /b
)
del "%out%"
REM Rest of script goes here

【讨论】:

  • 出于某种原因,使用它只会使批处理非常快速地打开和关闭,即使最后有暂停也是如此。目前不确定它是什么,但通常是因为某处的一些错字。
  • @user2150312 - 看看逻辑 - 暂停需要在 IF 块内。已编辑。
【解决方案2】:

如果您想要做的只是回显给您回显总数的名称,您可以使用这个:

@echo off & Setlocal
:: Search for files in the Tree
Set "sFolder=C:\temp"
Set "sFileType=txt"
set "i=0"

PushD "%sFolder%" &&(
      FOR /R "." %%i IN (*) DO ( If /i "%%~xi"==".%sFileType%" ( set /a i+=1 &echo %%~ni) ) )

【讨论】:

  • 这似乎很容易,但有没有办法在 GOTO notifyuser 之后回显文件?您是否只需将 %%~n1 -> 放入 %%t 之类的变量...然后稍后在脚本中回显 %%t ?
  • 在这种情况下使用@aschipfl 解决方案,他基本上做同样的事情,但将所有名称存储在数组变量中(如 ITEM[1] ..ITEM[2] 等,然后在notifyuser 部分使用他的解决方案的最后一部分,因为变量已经设置,输出每个 ITEM[n] 直到他达到总数。
【解决方案3】:

@dbenham's answer 中可能提供了最简单的解决方案。但是,我想在不使用临时文件但使用 (a) 变量来存储文本文件列表的情况下给出答案。


以下脚本基于您的for /R 方法,并建立一个以逗号分隔的已找到*.txt 文件列表(每个都包含在"" 中)并将其存储在变量ITEMS 中。一个标准的for 循环用于显示列表项,以防数量超过预定义的限制。这里是:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Define constants here:
set "LOCATION=.."
set "PATTERN=*.txt"
set /A LIMIT=2

set /A COUNT=0
set "ITEMS="
pushd "%LOCATION%" && (
    for /R "." %%F in ("%PATTERN%") do (
        set /A COUNT+=1
        set "ITEM=%%~F"
        setlocal EnableDelayedExpansion
        for /F "delims=" %%S in ("!ITEMS!"!ITEM!",") do (
            endlocal
            set "ITEMS=%%S"
        )
    )
    popd
)
if %COUNT% GTR %LIMIT% (
    echo Cannot continue script, too many "%PATTERN%" files ^(%COUNT%^) encountered:
    for %%F in (%ITEMS%) do (
        echo(%%~F
    )
    exit /B
)

rem Continue script here...

endlocal
exit /B

由于环境变量的大小和命令行的长度是有限的(在 Windows 7 x64 上,我认为都是 8191 字节),对于找到的大量 *.txt 文件,此方法可能会失败。


这个脚本略有不同,使用类数组变量ITEM[1]ITEM[2]ITEM[3]等来存储遇到的*.txt文件(各一个)。

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Define constants here:
set "LOCATION=.."
set "PATTERN=*.txt"
set /A LIMIT=2

set /A COUNT=0
pushd "%LOCATION%" && (
    for /R "." %%F in ("%PATTERN%") do (
        set /A COUNT+=1
        set "ITEM=%%~F"
        setlocal EnableDelayedExpansion
        for /F "tokens=1,* delims=|" %%S in ("!COUNT!|!ITEM!") do (
            endlocal
            set "ITEM[%%S]=%%T"
        )
    )
    popd
)
if %COUNT% GTR %LIMIT% (
    echo Cannot continue script, too many "%PATTERN%" files ^(%COUNT%^) encountered:
    for /L %%F in (1,1,%COUNT%) do (
        setlocal EnableDelayedExpansion
        echo(!ITEM[%%F]!
        endlocal
    )
    exit /B
)

rem Continue script here...

endlocal
exit /B

这里的环境大小(包含所有环境变量的空间)是限制;我不知道上限,但应该相当高。

【讨论】:

    猜你喜欢
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-27
    • 2018-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多