web-dev-qa-db-fra.com

SI ... OR SI ... dans un fichier batch Windows

Existe-t-il un moyen d'écrire une instruction conditionnelle IF OR IF dans un fichier de commandes Windows?

Par exemple:

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

La solution zmbq est bonne, mais ne peut pas être utilisée dans toutes les situations, par exemple dans un bloc de code tel qu'une boucle FOR DO (...).

Une alternative consiste à utiliser une variable indicatrice. Initialisez-le pour qu'il soit indéfini, puis définissez-le uniquement si l'une des conditions OR est vraie. Ensuite, utilisez IF DEFINED comme test final - inutile d’utiliser une expansion retardée.

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

Vous pouvez ajouter la logique ELSE IF utilisée par arasmussen, au motif qu’elle pourrait effectuer un petit peu plus vite si la 1ère condition est vraie, mais je ne me dérange jamais.

Addendum - Il s'agit d'une question en double avec des réponses presque identiques à tilisation d'un OR dans une instruction IF WinXP Batch Script

Addendum final - J'ai presque oublié ma technique préférée pour tester si une variable est une liste des valeurs. Initialisez une variable de test contenant une liste délimitée de valeurs acceptables, puis utilisez la fonction de recherche et remplacement pour vérifier si votre variable figure dans la liste. Ceci est très rapide et utilise un code minimal pour une liste arbitrairement longue. Cela nécessite une expansion retardée (ou le tour CALL %% VAR %%). Le test est également CASEN INSENSITIVE.

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 le VAR contient =, le test n’est donc pas infaillible.

Si vous effectuez le test dans un bloc où une expansion retardée est nécessaire pour accéder à la valeur actuelle de VAR,

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)
)

Des options FOR telles que "delims =" peuvent être nécessaires en fonction des valeurs attendues dans VAR

La stratégie ci-dessus peut être rendue fiable même avec = dans 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 clause ELSE à moins d’ajouter une variable indicatrice. Le code a commencé à paraître un peu "laid", mais je pense que c'est la méthode la plus fiable et la plus performante pour tester si VAR correspond à un nombre arbitraire d'options insensibles à la casse.

Enfin, il existe une version plus simple qui, à mon avis, est un peu plus lente car elle doit effectuer un IF pour chaque valeur. Aacini a fourni cette solution dans un commentaire sur la réponse acceptée dans le lien mentionné précédemment

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

La liste de valeurs ne peut pas inclure le * ou? caractères, et les valeurs et %VAR% ne doivent pas contenir de guillemets. Les citations posent des problèmes si le %VAR% contient également des espaces ou des caractères spéciaux tels que ^, & etc. Une autre limitation de cette solution est qu’elle ne permet pas l’option d’une ajouter une variable indicatrice. Les avantages sont qu'il peut être sensible à la casse ou insensible, selon la présence ou non de l'option IF /I.

85
dbenham

Je ne pense pas. Il suffit d'utiliser deux FI et GOTO la même étiquette:

IF cond1 GOTO foundit
IF cond2 GOTO foundit

ECHO Didn't found it
GOTO end

:foundit
ECHO Found it!

:end
46
zmbq

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

Je ne sais pas si cela peut aider mais j'ai eu le problème et grâce à vous, j'ai trouvé ce que je pense est un autre moyen de le résoudre en fonction de cette équivalence booléenne:

"A ou B" est identique à "pas (pas A et pas B)"

Ainsi:

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

Devient:

IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
7
Cactus

Même si cette question est un peu plus âgée:

Si vous voulez utiliser if cond1 or cond 2 - vous ne devriez pas utiliser de boucles compliquées ou des choses comme ça.

Simple fournir les deux ifs l'un après l'autre combinés 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 aller à l'action mais "inplace", vous pouvez exécuter l'action trois fois, si TOUTES les conditions correspondent.

5
dognose

Un simple "FOR" peut être utilisé sur 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
4
Apostolos

Il n'y a pas de IF <arg> OR ou Elif ou ELSE IF dans Batch, cependant ...

Essayez d'imbriquer l'autre SI à l'intérieur de l'ESI du SI précédent.

IF <arg> (
    ....
) ELSE (
    IF <arg> (
        ......
    ) ELSE (
        IF <arg> (
            ....
        ) ELSE (
    )
)
2
Andrew Rasmussen

L'objectif peut être atteint en utilisant les FI indirectement.

Vous trouverez ci-dessous un exemple d'expression complexe qui peut être écrite de manière très concise et logique dans un lot CMD, sans étiquettes incohérentes ni GOTO.

Les blocs de code entre crochets () sont traités par CMD comme un type de sous-shell (pathétique). Quel que soit le code de sortie sortant d'un bloc, il sera utilisé pour déterminer la valeur vraie/fausse que le bloc lit dans une expression booléenne plus grande. Des expressions booléennes arbitrairement grandes peuvent être construites avec ces blocs de code.

exemple simple

Chaque bloc est résolu en vrai (c'est-à-dire ERRORLEVEL = 0 après l'exécution de la dernière instruction du bloc)/false, jusqu'à ce que la valeur de l'expression entière ait été déterminée ou que le contrôle saute (par exemple, via GOTO):

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

Exemple complexe

Cela résout le problème soulevé initialement. Plusieurs déclarations sont possibles dans chaque bloc mais dans le || || || expression, il est préférable d’être concis pour que ce soit aussi lisible que possible. ^ est un caractère d'échappement dans les lots CMD et placé à la fin d'une ligne, il échappera à la fin de ligne et demandera à CMD de continuer à lire le lot d'instructions en cours 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
bogdan

Il est possible d'utiliser une fonction qui évalue la logique OR et renvoie une valeur unique.

@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
jeb
If %x%==1 (
If %y%==1 (
:: both are equal to 1.
)
)

C'est pour vérifier si plusieurs variables ont la même valeur. Voici pour l'une ou l'autre variable.

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

Je viens de penser à cela du haut si ma tête. Je pourrais le compacter plus.

1
coltonon

Je me rends compte que cette question est ancienne, mais je voulais poster une solution alternative au cas où quelqu'un d'autre (comme moi) trouverait ce fil tout en posant la même question. J'ai pu contourner le manque d'opérateur OR 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
AKAJim

Bien que la réponse de dbenham soit plutôt bonne, compter sur IF DEFINED peut vous causer énormément de problèmes si la variable que vous vérifiez n'est pas un environnement variable. Les variables de script ne reçoivent pas ce traitement spécial.

Bien que cela puisse sembler une BS sans papiers ridicule, faire une simple requête Shell de IF avec IF /? révèle que,

Le conditionnel DEFINED fonctionne exactement comme EXIST sauf qu'il prend un nom de variable environment et renvoie true si environnement la variable est définie.

En ce qui concerne la réponse à cette question, y a-t-il une raison de ne pas utiliser un simple drapeau après une série d'évaluations? Cela me semble le contrôle le plus flexible OR, tant en ce qui concerne la logique sous-jacente que la lisibilité. Par 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, il peut s’agir d’une évaluation conditionnelle, mais je ne donne que quelques exemples.

Si vous voulez tout avoir sur une seule ligne, en écriture, vous pouvez simplement les chaîner 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
kayleeFrye_onDeck

Je n'ai jamais existé pour travailler.

J'utilise sinon existez g: xyz/ce qui est arrivé: autre xcopy c: actuel/fichiers g: bu/actuel Il y a des modificateurs/a etc. Je ne sais pas lesquels. Ordinateur portable dans la boutique. Et l'ordinateur au bureau. Je ne suis pas là.

Jamais les fichiers de commandes ne fonctionnent au-dessus de Windows XP

0
user8865291