57

这是我想要的,在里面BACKUPDIR,我想执行cscript /nologo c:\deletefile.vbs %BACKUPDIR%,直到文件夹内的文件数大于 21(countfiles保存它)。这是我的代码:

@echo off
SET BACKUPDIR=C:\test
for /f %%x in ('dir %BACKUPDIR% /b ^| find /v /c "::"') do set countfiles=%%x

for %countfiles% GTR 21 (
cscript /nologo c:\deletefile.vbs %BACKUPDIR%
set /a countfiles-=%countfiles%
)
4

5 回答 5

64
set /a countfiles-=%countfiles%

这会将 countfiles 设置为 0。我认为您想将其减少 1,因此请改用:

set /a countfiles-=1

我不确定for循环是否会起作用,最好尝试这样的事情:

:loop
cscript /nologo c:\deletefile.vbs %BACKUPDIR%
set /a countfiles-=1
if %countfiles% GTR 21 goto loop
于 2009-11-24T07:48:00.913 回答
60

while可以使用以下方法模拟循环cmd.exe

:still_more_files
    if %countfiles% leq 21 (
        rem change countfile here
        goto :still_more_files
    )

例如,以下脚本:

    @echo off
    setlocal enableextensions enabledelayedexpansion
    set /a "x = 0"

:more_to_process
    if %x% leq 5 (
        echo %x%
        set /a "x = x + 1"
        goto :more_to_process
    )

    endlocal

输出:

0
1
2
3
4
5

对于您的特定情况,我将从以下内容开始。你最初的描述有点混乱。我假设您要删除该目录中的文件,直到有 20 个或更少:

    @echo off
    set backupdir=c:\test

:more_files_to_process
    for /f %%x in ('dir %backupdir% /b ^| find /v /c "::"') do set num=%%x
    if %num% gtr 20 (
        cscript /nologo c:\deletefile.vbs %backupdir%
        goto :more_files_to_process
    )
于 2009-11-24T07:43:50.953 回答
9

我有一个技巧来做到这一点!

我想出了这种方法,因为在 CLI 上,无法使用此处其他答案中提供的方法,而且它一直困扰着我。

我称之为“直到中断”或“无限”循环:

基本示例

FOR /L %L IN (0,0,1) DO @(
 ECHO. Counter always 0, See "%L" = "0" - Waiting a split second&ping -n 1 127.0.0.1>NUL )

这真是一个无限循环!

这对于监视CMD窗口中的某些内容很有用,并允许您在完成后使用CTRL+C来破坏它。

想要柜台吗?

要么使用SET /AOR 您可以修改FOR /L循环来进行计数并且仍然是无限的(注意,这两种方法都有 32 位整数溢出)

SET /A方法:

FOR /L %L IN (0,0,1) DO @(
 SET /A "#+=1"&ECHO. L Still equals 0, See "%L = 0"!  - Waiting a split second &ping -n 1 127.0.0.1>NUL  )

本机FOR /L计数器:

FOR /L %L IN (-2147483648,1,2147483648) DO @(
 ECHO.Current value of L: %L - Waiting a split second &ping -n 1 127.0.0.1>NUL  )

计数 4294967295 组并显示 L 的当前值:

FOR /L %L IN (1,1,2147483648) DO @(
 (
  IF %L EQU 0 SET /A "#+=1">NUL
 )&SET /A "#+=0"&ECHO. Sets of 4294967295 - Current value of L: %L - Waiting a split second &ping -n 1 127.0.0.1>NUL )

但是,如果:

  • 您有兴趣查看监视器的输出,并担心我会在完成后检查它之前通过 9999 行缓冲区限制。
  • 一旦我正在监视的事物完成,您想采取一些额外的行动。

为此,我确定了如何使用几种方法FOR过早地打破循环,有效地将其变成“ DO WHILE”或“ DO UNTIL”循环,否则 CMD 非常缺乏这种循环。

注意:大多数情况下,循环将继续迭代您检查的条件,这通常是一种想要的行为,但在我们的例子中不是。

将“无限循环”变成“ DO WHILE”/“ DO UNTIL”循环

更新:由于想在 CMD 脚本(并让它们持久化!)以及 CLI 中使用此代码,并且考虑是否可能有“更正确”的方法来实现这一点,我建议使用新方法!

新方法(可以在 CMD 脚本中使用而无需退出脚本):

FOR /F %%A IN ('
  CMD /C "FOR /L %%L IN (0,1,2147483648) DO @( ECHO.%%L & IF /I %%L EQU 10 ( exit /b  ) )"
') DO @(
  ECHO %%~A
)

在 CLI:

FOR /F %A IN ('
  CMD /C "FOR /L %L IN (0,1,2147483648) DO @( ECHO.%L & IF /I %L EQU 10 ( exit /b  ) )"
') DO @(
  ECHO %~A
)

原始方法(可以在 CLI 上正常工作,但会杀死脚本。)

FOR /L %L IN (0,1,2147483648) DO @(
  ECHO.Current value of L: %L - Waiting a split second &ping -n 1 127.0.0.1>NUL&(
    IF /I %L EQU 10 (
      ECHO.Breaking the Loop! Because We have matched the condition!&DIR >&0
    )
  )
) 2>NUL

较早的帖子

偶然的机会,我发现了一些过早退出循环的方法,这些方法在尝试做其他给我这个想法的事情时并没有关闭 CMD 提示。

笔记:

虽然ECHO.>&3 >NUL在某些情况下对我有用,但多年来我断断续续地玩这个,发现它DIR >&0 >NUL更加一致。

我正在从这里重新编写这个答案以使用该方法,因为我最近发现自己的旧笔记改为使用此方法。

用更好的方法编辑的帖子如下:

DIR >&0 >NUL

>NUL 是可选的,我只是不想让它输出错误。

我更喜欢在可能的情况下匹配 inLine,正如您在我用于监控 VNX 上的 LUN 迁移的命令的净化示例中所见。

for /l %L IN (0,0,1) DO @(
   ECHO.& ECHO.===========================================& (
     [VNX CMD] | FINDSTR /R /C:"Source LU Name" /C:"State:" /C:"Time " || DIR >&0 >NUL
   ) & Ping -n 10 1.1.1.1 -w 1000>NUL )

另外,我在给自己的笔记中发现了另一种方法,我刚刚重新测试了它以确认在 CLI 上的工作方式与另一种方法一样好。

显然,当我第一次在这里发帖时,我发布了一个我正在玩的旧版本,而不是两个更好的新版本:

在此方法中,我们使用EXIT /B退出 For 循环,但我们不想退出 CLI,因此我们将其包装在 CMD 会话中:

FOR /F %A IN ('CMD /C "FOR /L %L IN (0,1,10000000) DO @( ECHO.%L & IF /I %L EQU 10 ( exit /b  ) )" ') DO @(ECHO %~A)

因为循环本身发生在 CMD 会话中,我们可以使用 EXIT /B 退出循环的迭代,而不会丢失我们的 CMD 会话,也无需等待循环完成,这与其他方法非常相似。

我什至会说这种方法可能是您想要在 CLI 上打破 for 循环的那种场景的“预期”方法,因为使用 CMD 会话也是使延迟扩展工作的唯一方法循环的 CLI,以及行为和此类行为显然是离开 CMD 会话的预期工作流。

IE:Microsoft 显然有意让 CMD Exit /B For 循环以这种方式运行,而作为我的另一种方法,这样做的“预期”方式依赖于意外创建正确的错误以将您踢出循环而不让循环完成处理,这是我偶然发现的,并且似乎只有在使用相当奇怪的 DIR 命令时才能可靠地工作。

也就是说,我认为使用方法 2 可能是一种更好的做法:

FOR /F %A IN ('CMD /C "FOR /L %L IN (0,1,10000000) DO @( ECHO.%L & IF /I %L EQU 10 ( exit /b  ) )" ') DO @(ECHO %~A)

虽然我怀疑方法 1 会稍微快一些:

FOR /L %L IN (0,1,10000000) DO @( ECHO.%L & IF /I %L EQU 10 ( DIR >&) >NUL ) )

在任何一种情况下,两者都应该根据您的目的允许 DO-While 循环。

于 2019-02-21T22:25:53.340 回答
8
@echo off

set countfiles=10

:loop

set /a countfiles -= 1

echo hi

if %countfiles% GTR 0 goto loop

pause

在第一个“set countfiles”上,你看到的 10 是它将循环的数量 echo hi 是你想要循环的东西

...我晚了 5 年

于 2015-05-14T01:42:57.797 回答
2

这对我来说非常有用,我用以下方式在活动目录中添加用户:

:: This file is used to automatically add list of user to activedirectory
:: First ask for username,pwd,dc details and run in loop
:: dsadd user cn=jai,cn=users,dc=mandrac,dc=com -pwd `1q`1q`1q`1q

@echo off
setlocal enableextensions enabledelayedexpansion
set /a "x = 1"
set /p lent="Enter how many Users you want to create : "
set /p Uname="Enter the user name which will be rotated with number ex:ram then ram1 ..etc : "
set /p DcName="Enter the DC name ex:mandrac : "
set /p Paswd="Enter the password you want to give to all the users : "

cls

:while1

if %x% leq %lent% (

    dsadd user cn=%Uname%%x%,cn=users,dc=%DcName%,dc=com -pwd %Paswd%
    echo User %Uname%%x% with DC %DcName% is created
    set /a "x = x + 1"
    goto :while1
)

endlocal
于 2011-08-19T12:37:47.217 回答