web-dev-qa-db-ja.com

バッチでのwhileループ

BACKUPDIR内で、フォルダー内のファイル数が21を超えるまで(countfilesが保持するまで)cscript /nologo c:\deletefile.vbs %BACKUPDIR%を実行します。ここに私のコードがあります:

@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%
)
42
Hellnar
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
53
schnaader

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
    )
46
paxdiablo
@echo off

set countfiles=10

:loop

set /a countfiles -= 1

echo hi

if %countfiles% GTR 0 goto loop

pause

最初の「set countfiles」では、表示される10はエコーをループする量です。hiはループしたいものです

...私は5年遅れています

6
luke

これを行うコツがあります!

この方法を思いついたのは、CLI上では、他の回答で提供されている方法を使用することができず、常に私を悩ませていたからです。

これを「Do Until Break」または「Infinite」ループと呼びます。

基本的な例

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 /A ORのいずれかを使用します。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」ループに変換する方法を決定しました。

注:ほとんどの場合、ループはチェックした条件を超えて反復し続けます。多くの場合、これは望ましい動作ですが、この場合はそうではありません。

「無限ループ」を「DO WHILE」/「DO UNTIL」ループに変える

更新:CMDスクリプトでこのコードを使用する(およびそれらを永続化させる)ために、CLIを使用し、これを達成するための「より正しい」方法があるかどうかを考えると、Newメソッドを使用することをお勧めします!

新しいメソッド(スクリプトを終了せずに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
)

Original Method(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はオプションです。エラーを出力しないようにしたいだけです。

VNXでLUN移行を監視するために使用するコマンドのサニタイズされたこの例でわかるように、可能な場合はinLineを照合することを好みます。

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で他の方法と同じように機能することを確認するために再テストしたばかりの、自分自身に対するメモで見つけた別の方法があります。

どうやら、最初にここに投稿したとき、私はより良い2つの新しいものの代わりに、遊んでいた古い反復を投稿しました:

この方法では、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:マイクロソフトは、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ループを許可する必要があります。

3
Ben Personick

Active Directoryにユーザーを追加するために次の方法で使用しました。

:: 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
2
jayaram