Si... ou si... dans un fichier Windows batch

y a-t-il un moyen d'écrire un SI ou si conditionnel dans un fichier Windows batch?

par exemple:

IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
69
demandé sur Mechaflash 2011-12-09 02:19:36

13 réponses

la solution zmbq est bonne, mais ne peut pas être utilisée dans toutes les situations, comme à l'intérieur d'un bloc de code comme un pour DO(...) boucle.

une autre solution consiste à utiliser une variable indicatrice. L'initialiser à être indéfini, puis la définir que si l'une quelconque de la OU des conditions est vraie. Puis utiliser si défini comme un test final - pas besoin d'utiliser l'expansion retardée.

FOR ..... DO (
  set "TRUE="
  IF cond1 set TRUE=1
  IF cond2 set TRUE=1
  IF defined TRUE (
    ...
  ) else (
    ...
  )
)

vous pouvez ajouter L'autre si logique que l'arasmussen utilise sur les motifs que il pourrait fonctionner un peu plus vite si la 1ère condition est vraie, mais je ne me donne jamais la peine.

Addendum - il S'agit D'une question en double avec des réponses presque identiques à à L'aide D'un ou dans une déclaration en Lot de WinXP

"addendum Final - j'ai presque oublié ma technique préférée pour tester si une variable est une de liste de valeurs. Initialisez une variable de test contenant une liste délimitée de valeurs acceptables, puis utilisez recherche et remplacer pour tester si votre variable est dans la liste. C'est très rapide et utilise du code minimal pour une liste arbitrairement longue. Il ne nécessite pas d'expansion retardée (ou bien L'appel %%VAR%% astuce). De plus, le test est insensible à la casse.

set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" (echo true) else (echo false)

ce qui précède peut échouer si VAR contient = , de sorte que le test n'est pas infaillible.

Si faire l'essai dans un bloc où l'expansion retardée est nécessaire pour accéder à la valeur courante de VAR alors

for ... do (
  set "TEST=;val1;val2;val3;val4;val5;"
  for /f %%A in (";!VAR!;") do if "!TEST:%%A=!" neq "!TEST!" (echo true) else (echo false)
)

pour les options comme "delims=" peut être nécessaire en fonction des valeurs attendues dans la VAR

la stratégie ci-dessus peut être rendue fiable même avec = dans le VAR en ajoutant un peu plus de code.

set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" if "!TEST:;%VAR%;=;%VAR%;"=="!TEST!" echo true

mais maintenant nous avons perdu la possibilité de fournir une autre clause à moins que nous ajoutions une variable indicatrice. Le code a commencé à sembler un peu "laid", mais je pense qu'il est la meilleure méthode fiable pour tester si VAR est l'un d'un nombre arbitraire d'options insensibles à la casse.

enfin il y a une version plus simple qui je pense est légèrement plus lente parce qu'elle doit effectuer un si pour chaque valeur. Aacini a fourni cette solution dans un commentaire à la réponse acceptée dans le lien ci-dessus mentionné

for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A do echo true

la liste de valeurs ne peut pas inclure les * ou ? les caractères, et les valeurs et %VAR% ne doivent pas contenir de guillemets. Les guillemets posent des problèmes si le %VAR% contient aussi des espaces ou des caractères spéciaux comme ^ , & etc. Une autre limitation avec cette solution est qu'elle ne fournit pas l'option pour une autre clause à moins que vous ajoutiez une variable indicatrice. Les avantages sont qu'il peut être sensible à la casse ou insensible selon la présence ou l'absence de si /I option.

75
répondu dbenham 2017-05-23 12:10:05

Je ne pense pas. Il suffit d'utiliser deux IFs et de passer à la même étiquette:

IF cond1 GOTO foundit
IF cond2 GOTO foundit

ECHO Didn't found it
GOTO end

:foundit
ECHO Found it!

:end
41
répondu zmbq 2012-09-12 11:30:23

Merci pour ce post, il m'a beaucoup aidé.

Je ne sais pas si ça peut aider mais j'ai eu le problème et grâce à vous j'ai trouvé ce que je pense être une autre façon de le résoudre basé sur cette équivalence booléenne:

"A ou B" est le même que le "non(non A et non B)"

ainsi:

IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE

devient:

IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
6
répondu Cactus 2014-06-25 14:48:56

même si cette question est un peu plus ancienne:

Si vous voulez utiliser if cond1 or cond 2 - vous ne devez pas utiliser compliqué boucles ou des trucs comme ça.

simple fournir les deux ifs après l'autre combiné avec goto - c'est un ou implicite.

//thats an implicit IF cond1 OR cond2 OR cond3
if cond1 GOTO doit
if cond2 GOTO doit
if cond3 GOTO doit

//thats our else.
GOTO end

:doit
  echo "doing it"

:end

sans goto mais une action" inplace", vous pourriez exécuter l'action 3 fois, si toutes les conditions sont identiques.

4
répondu dognose 2014-04-11 16:35:33

il n'y a pas de IF <arg> OR ou ELIF ou ELSE IF dans le lot, cependant...

essayez d'imiter l'autre IF à l'intérieur de L'autre IF.

IF <arg> (
    ....
) ELSE (
    IF <arg> (
        ......
    ) ELSE (
        IF <arg> (
            ....
        ) ELSE (
    )
)
2
répondu Andrew Rasmussen 2011-12-08 22:23:23

le but peut être atteint en utilisant L'IFs indirectement.

ci-dessous est un exemple d'une expression complexe qui peut être écrite de façon très concise et logique dans un lot CMD, sans étiquettes et GOTOs incohérents.

les blocs de Code entre () parenthèses sont traités par CMD comme une sorte de sous-cellule (pathétique). Quel que soit le code de sortie qui sort d'un bloc, il sera utilisé pour déterminer la valeur vraie/fausse que le bloc joue dans une expression booléenne plus grande. Arbitrairement grand expressions booléennes peuvent être construites avec des blocs de code.

exemple Simple

chaque bloc est résolu à true (i.e. ERRORLEVEL = 0 après la dernière instruction dans le bloc a exécuté) / false, jusqu'à ce que la valeur de l'expression entière ait été déterminée ou le contrôle saute dehors (par exemple via GOTO):

 ((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)

exemple complexe

cela résout le problème posé initialement. Des déclarations multiples sont possibles dans chaque bloc mais dans le|| || || expression il est préférable d'être concis afin d'être aussi lisible que possible. ^ est un caractère d'échappement dans les lots CMD et lorsqu'il est placé à la fin d'une ligne, il échappera à la fin de vie et demandera au CMD de continuer à lire le lot actuel d'énoncés sur la ligne suivante.

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

(
    (CALL :ProcedureType1 a b) ^
        || (CALL :ProcedureType2 sgd) ^
            || (CALL :ProcedureType1 c c)
) ^
    && (
        ECHO -=BINGO=-
        GOTO :EOF
    )
ECHO -=no bingo for you=-
GOTO :EOF

:ProcedureType1
    IF "%~1" == "%~2" (EXIT /B 0) ELSE (EXIT /B 1)
GOTO :EOF (this line is decorative as it's never reached)

:ProcedureType2
    ECHO :ax:xa:xx:aa:|FINDSTR /I /L /C:":%~1:">nul
GOTO :EOF
2
répondu bogdan 2014-09-12 17:25:51

il est possible d'utiliser une fonction, qui évalue la logique OR et renvoie une seule valeur.

@echo off
set var1=3
set var2=5
call :logic_or orResult "'%var1%'=='4'" "'%var2%'=='5'"
if %orResult%==1 ( 
    echo At least one expression is true
) ELSE echo All expressions are false
exit /b

:logic_or <resultVar> expression1 [[expr2] ... expr-n] 
SETLOCAL
set "logic_or.result=0"
set "logic_or.resultVar=%~1"

:logic_or_loop 
if "%~2"=="" goto :logic_or_end 
if %~2 set "logic_or.result=1"
SHIFT 
goto :logic_or_loop 

:logic_or_end 
( 
  ENDLOCAL 
  set "%logic_or.resultVar%=%logic_or.result%"
  exit /b
) 
1
répondu jeb 2013-04-29 16:51:11
If %x%==1 (
If %y%==1 (
:: both are equal to 1.
)
)

C'est pour vérifier si plusieurs variables égale valeur. Voici pour chaque variable.

If %x%==1 (
:: true
)
If %x%==0 (
If %y%==1 (
:: true
)
)
If %x%==0 (
If %y%==0 (
:: False
)
)

je viens d'y penser. Je pourrais le compacter plus.

1
répondu coltonon 2014-07-20 18:12:53

je réalise que cette question Est ancienne, mais je voulais poster une solution alternative au cas où quelqu'un d'autre (comme moi) a trouvé ce fil tout en ayant la même question. J'ai pu contourner le manque d'opérateur RO en faisant écho à la variable et en utilisant findstr pour valider.

for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do (
    if %errorlevel% equ 0 echo true
)
1
répondu AKAJim 2014-08-11 23:42:45

simple "POUR" peut être utilisé en une seule ligne pour utiliser une condition "ou":

FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command}  

appliqué à votre cas:

FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE
1
répondu Apostolos 2018-07-22 07:51:50

tandis que la réponse de dbenham est assez bonne, en se basant sur IF DEFINED peut vous mettre dans des tas de problèmes si la variable que vous cochez n'est pas une environnement variable. Les variables de Script ne reçoivent pas ce traitement spécial.

bien que cela puisse sembler être une sorte de BS non documentée, faire une simple requête shell de IF avec IF /? révèle que,

les travaux conditionnels définis tout comme Existe sauf qu'il faut un environnement nom de la variable et retourne true si la environnement variable est défini.

en ce qui concerne la réponse à cette question, y a-t-il une raison pour ne pas simplement utiliser un simple drapeau après une série d'évaluations? Cela me semble le contrôle le plus flexible OR , à la fois en ce qui concerne la logique sous-jacente et la lisibilité. Pour exemple:

Set Evaluated_True=false

IF %condition_1%==true (Set Evaluated_True=true)
IF %some_string%=="desired result" (Set Evaluated_True=true)
IF %set_numerical_variable% EQ %desired_numerical_value% (Set Evaluated_True=true)

IF %Evaluated_True%==true (echo This is where you do your passing logic) ELSE (echo This is where you do your failing logic)

évidemment, ils peuvent être n'importe quelle sorte d'évaluation conditionnelle, mais je partage juste quelques exemples.

si vous voulez avoir tout sur une ligne, écrit-sage, vous pouvez juste les enchaîner ensemble avec && comme:

Set Evaluated_True=false

IF %condition_1%==true (Set Evaluated_True=true) && IF %some_string%=="desired result" (Set Evaluated_True=true) && IF %set_numerical_variable% EQ %desired_numerical_value% (Set Evaluated_True=true)

IF %Evaluated_True%==true (echo This is where you do your passing logic) ELSE (echo This is where you do your failing logic)
0
répondu kayleeFrye_onDeck 2016-08-19 01:52:50

N'a jamais existé pour travailler.

j'utilise s'il n'existe pas g:xyz/what goto h: Autre xcopie c:current/files g:bu/current Il y a des modificateurs /a etc. Pas sûr que ceux qui. Ordinateur portable dans la boutique. Et ordinateur au bureau. Je ne suis pas là.

N'a jamais obtenu de fichiers par lot pour fonctionner au-dessus de Windows XP

0
répondu user8865291 2017-10-31 23:16:32

réalisant que c'est un peu une vieille question, les réponses m'ont aidé à trouver une solution pour tester les arguments en ligne de commande dans un fichier batch; donc je voulais poster ma solution aussi bien au cas où quelqu'un d'autre était à la recherche d'une solution similaire.

la première chose que je dois souligner est que j'avais du mal à obtenir si ... Autres déclarations à travailler à l'intérieur d'un pour ... FAIRE de la clause. Il s'avère (merci à dbenham pour avoir fait remarquer par inadvertance ceci dans ses exemples) L'énoncé "ELSE" ne peut pas être placé sur une ligne distincte des paren de clôture.

donc à la place de ceci:

FOR ... DO (
    IF ... (
    )
    ELSE (
    )
)

qui est ma préférence pour la lisibilité et les raisons esthétiques, vous devez le faire:

FOR ... DO (
    IF ... (
    ) ELSE (
    )
)

maintenant la déclaration ELSE ne revient pas comme une commande non reconnue.

enfin, voici ce que j'ai essayé de faire - je voulais pouvoir passer plusieurs arguments à un fichier batch dans n'importe quel ordre, ignorant cas, et rapport/échec sur les arguments non définis passés. Alors, voici ma solution...

@ECHO OFF
SET ARG1=FALSE
SET ARG2=FALSE
SET ARG3=FALSE
SET ARG4=FALSE
SET ARGS=(arg1 Arg1 ARG1 arg2 Arg2 ARG2 arg3 Arg3 ARG3)
SET ARG=

FOR %%A IN (%*) DO (
    SET TRUE=
    FOR %%B in %ARGS% DO (
        IF [%%A] == [%%B] SET TRUE=1
        )
    IF DEFINED TRUE (
        SET %%A=TRUE
        ) ELSE (
        SET ARG=%%A
        GOTO UNDEFINED
        )
    )

ECHO %ARG1%
ECHO %ARG2%
ECHO %ARG3%
ECHO %ARG4%
GOTO END

:UNDEFINED
ECHO "%ARG%" is not an acceptable argument.
GOTO END

:END

Note, Ceci rapportera seulement sur le premier argument échoué. Donc, si l'utilisateur passe dans plus d'un argument inacceptable, ils ne seront informés de la première jusqu'à ce qu'il soit corrigé, puis la seconde, etc

-3
répondu RMWChaos 2012-09-10 15:25:39