web-dev-qa-db-fra.com

Quelle est la bonne façon de vérifier si un paramètre est vide dans un fichier de commandes?

Je dois tester si une variable est définie ou non. J'ai essayé plusieurs techniques mais elles semblent échouer chaque fois que %1 est entouré de guillemets, tel que le cas où %1 est "c:\some path with spaces".

IF NOT %1 GOTO MyLabel // This is invalid syntax
IF "%1" == "" GOTO MyLabel // Works unless %1 has double quotes which fatally kills bat execution
IF %1 == GOTO MyLabel // Gives an unexpected GOTO error.

Selon ce site , il s’agit des types de syntaxe IF supportés. Donc, je ne vois pas le moyen de le faire.

IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXIST filename command
171
blak3r

Utilisez des crochets au lieu de guillemets:

IF [%1] == [] GOTO MyLabel

Les parenthèses sont non sécurisées : utilisez uniquement des crochets.

235
Dan Story

Vous pouvez utiliser:

IF "%~1" == "" GOTO MyLabel

dépouiller l'ensemble extérieur de guillemets. En général, il s'agit d'une méthode plus fiable que l'utilisation de crochets car elle fonctionnera même si la variable contient des espaces.

118
jamesdlin

Une des meilleures solutions semi consiste à copier %1 dans une variable, puis à utiliser l’expansion différée, en tant que delayExp. est toujours protégé contre tout contenu. 

set "param1=%~1"
setlocal EnableDelayedExpansion
if "!param1!"=="" ( echo it is empty )
rem ... or use the DEFINED keyword now
if defined param1 echo There is something

L'avantage de ceci est que traiter avec param1 est absolument sûr. 

Et la configuration de param1 fonctionnera dans de nombreux cas, comme

test.bat hello"this is"a"test
test.bat you^&me

Mais cela échouera avec des contenus étranges comme

test.bat "&"^&

Si vous voulez être à l'épreuve des balles à 99%, vous pouvez lire Comment recevoir les paramètres de ligne de commande les plus étranges?

31
jeb

De IF/?:

Si les extensions de commande sont activées IF change comme suit:

IF [/I] string1 compare-op string2 command
IF CMDEXTVERSION number command
IF DEFINED variable command

......

Le conditionnel DEFINED fonctionne seulement comme EXISTS sauf qu'il faut un nom de la variable d'environnement et retourne true si la variable d'environnement est défini.

15
Andy Morris

Utilisez "IF DEFINED variable command" pour tester la variable dans un fichier de commandes.

Mais si vous voulez tester les paramètres de lot, essayez les codes ci-dessous pour éviter les entrées difficiles (comme "1 2" ou ab ^> cd)

set tmp="%1"
if "%tmp:"=.%"==".." (
    echo empty
) else (
    echo not empty
)
5
zackz

La chaîne vide est une paire de double-quotes/"", nous pouvons simplement tester la longueur:

set ARG=%1
if not defined ARG goto nomore

set CHAR=%ARG:~2,1%
if defined CHAR goto goon

puis testez ses 2 caractères contre double-quotes:

if ^%ARG:~1,1% == ^" if ^%ARG:~0,1% == ^" goto blank
::else
goto goon

Voici un script batch avec lequel vous pouvez jouer. Je pense qu'il attrape correctement la chaîne vide.

Ceci est juste un exemple, vous avez juste besoin de personnaliser 2 (ou 3?) Étapes ci-dessus en fonction de votre script.

@echo off
if not "%OS%"=="Windows_NT" goto EOF
:: I guess we need enableExtensions, CMIIW
setLocal enableExtensions
set i=0
set script=%0

:LOOP
set /a i=%i%+1

set A1=%1
if not defined A1 goto nomore

:: Assumption:
:: Empty string is (exactly) a pair of double-quotes ("")

:: Step out if str length is more than 2
set C3=%A1:~2,1%
if defined C3 goto goon

:: Check the first and second char for double-quotes
:: Any characters will do fine since we test it *literally*
if ^%A1:~1,1% == ^" if ^%A1:~0,1% == ^" goto blank
goto goon

:goon
echo.args[%i%]: [%1]
shift
goto LOOP

:blank
echo.args[%i%]: [%1] is empty string
shift
goto LOOP

:nomore
echo.
echo.command line:
echo.%script% %*

:EOF

Ce résultat de test de torture:

.test.bat :: ""  ">"""bl" " "< "">"  (")(") "" :: ""-"  " "( )"">\>" ""
args[1]: [::]
args[2]: [""] is empty string
args[3]: [">"""bl" "]
args[4]: ["< "">"]
args[5]: [(")(")]
args[6]: [""] is empty string
args[7]: [::]
args[8]: [""-"  "]
args[9]: ["( )"">\>"]
args[10]: [""] is empty string

command line:
.test.bat :: ""  ">"""bl" " "< "">"  (")(") "" :: ""-"  " "( )"">\>" ""
3
user6801759

Malheureusement, je n'ai pas assez de réputation pour commenter ou voter sur les réponses actuelles. J'ai dû écrire les miennes.

A l'origine, la question de l'OP disait "variable" plutôt que "paramètre", ce qui était très déroutant, d'autant plus qu'il s'agissait du lien numéro un dans Google pour la recherche de la façon de tester les variables vides. Depuis ma réponse initiale, Stephan a modifié la question initiale pour utiliser la terminologie correcte. Cependant, plutôt que de supprimer ma réponse, j'ai décidé de la laisser afin de dissiper toute confusion, en particulier si Google envoie toujours des personnes ici pour les variables:

% 1 IS N'EST PAS UN VARABLE! IL IS UN PARAMÈTRE DE LIGNE DE COMMANDE.

Distinction très importante. Un seul signe de pourcentage avec un nombre après qu'il fasse référence à un paramètre de ligne de commande et non à une variable.

Les variables sont définies à l'aide de la commande set et sont rappelées avec 2 signes de pourcentage, un avant et un après. Par exemple,% myvar%

Pour tester une variable vide, utilisez la syntaxe "si non défini" (les commandes explicites pour les variables ne nécessitent aucun signe de pourcentage), par exemple:

set myvar1=foo  
if not defined myvar1 echo You won't see this because %myvar1% is defined.  
if not defined myvar2 echo You will see this because %myvar2% isn't defined.

(Si vous souhaitez tester les paramètres de ligne de commande, je vous recommande de vous reporter à la réponse de jamesdlin.)

3
user3343110

Script 1:

Entrée ("Supprimer Quotes.cmd" "Ceci est un test")

@ECHO OFF

REM Set "string" variable to "first" command line parameter
SET STRING=%1

REM Remove Quotes [Only Remove Quotes if NOT Null]
IF DEFINED STRING SET STRING=%STRING:"=%

REM IF %1 [or String] is NULL GOTO MyLabel
IF NOT DEFINED STRING GOTO MyLabel


REM   OR   IF "." equals "." GOTO MyLabel
IF "%STRING%." == "." GOTO MyLabel

REM GOTO End of File
GOTO :EOF

:MyLabel
ECHO Welcome!

PAUSE

Sortie (il n'y en a pas,% 1 n'était PAS vide, vide ou NULL):


Exécuter ("Remove Quotes.cmd") sans aucun paramètre avec le script ci-dessus 1

Sortie (% 1 est vide, vide ou NULL):

Welcome!

Press any key to continue . . .

Remarque: Si vous définissez une variable dans une instruction IF ( ) ELSE ( ), DEFINED ne sera disponible qu'après avoir quitté l'instruction "IF" (à moins que "Expansion de variable différée" soit activé; une fois activé, utilisez un point d'exclamation au lieu de le pourcentage "%" symbole}.

Par exemple:

Script 2:

Entrée ("Supprimer Quotes.cmd" "Ceci est un test")

@ECHO OFF

SETLOCAL EnableDelayedExpansion

SET STRING=%0
IF 1==1 (
  SET STRING=%1
  ECHO String in IF Statement='%STRING%'
  ECHO String in IF Statement [delayed expansion]='!STRING!'
) 

ECHO String out of IF Statement='%STRING%'

REM Remove Quotes [Only Remove Quotes if NOT Null]
IF DEFINED STRING SET STRING=%STRING:"=%

ECHO String without Quotes=%STRING% 

REM IF %1 is NULL GOTO MyLabel
IF NOT DEFINED STRING GOTO MyLabel

REM GOTO End of File
GOTO :EOF

:MyLabel
ECHO Welcome!

ENDLOCAL
PAUSE

Sortie:

C:\Users\Test>"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd" "This is a Test"  
String in IF Statement='"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"'  
String in IF Statement [delayed expansion]='"This is a Test"'  
String out of IF Statement='"This is a Test"'  
String without Quotes=This is a Test  

C:\Users\Test>  

Remarque: Cela supprimera également les guillemets de l'intérieur de la chaîne.

Par exemple (en utilisant le script 1 ou 2): C:\Utilisateurs\Test\Documents\Fichiers batch> "Supprimer Quotes.cmd" "Ceci est" un "Test"

Sortie (script 2):

String in IF Statement='"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"'  
String in IF Statement [delayed expansion]='"This is "a" Test"'  
String out of IF Statement='"This is "a" Test"'  
String without Quotes=This is a Test  

Execute ("Remove Quotes.cmd") sans aucun paramètre dans le script 2:

Sortie:

Welcome!

Press any key to continue . . .
2
Mr. Rick

Vous pouvez utiliser 

if defined (variable) echo That's defined!
if not defined (variable) echo Nope. Undefined.
2
noname

J'utilise habituellement ceci:

IF "%1."=="." GOTO MyLabel

Si% 1 est vide, le SI comparera "." à "." qui évaluera à vrai.

2
aphoria

Je teste avec le code ci-dessous et c'est bon.

@echo off

set varEmpty=
if not "%varEmpty%"=="" (
    echo varEmpty is not empty
) else (
    echo varEmpty is empty
)
set varNotEmpty=hasValue
if not "%varNotEmpty%"=="" (
    echo varNotEmpty is not empty
) else (
    echo varNotEmpty is empty
)
2
Kate

J'ai créé ce petit script batch basé sur les réponses ici, car il en existe de nombreuses valides. N'hésitez pas à ajouter à cela tant que vous suivez le même format:

REM Parameter-testing

Setlocal EnableDelayedExpansion EnableExtensions

IF NOT "%~1"=="" (echo Percent Tilde 1 failed with quotes) ELSE (echo SUCCESS)
IF NOT [%~1]==[] (echo Percent Tilde 1 failed with brackets) ELSE (echo SUCCESS)
IF NOT  "%1"=="" (echo Quotes one failed) ELSE (echo SUCCESS)
IF NOT [%1]==[] (echo Brackets one failed) ELSE (echo SUCCESS)
IF NOT "%1."=="." (echo Appended dot quotes one failed) ELSE (echo SUCCESS)
IF NOT [%1.]==[.] (echo Appended dot brackets one failed) ELSE (echo SUCCESS)

pause
2
kayleeFrye_onDeck

Pour résumer les choses:

set str=%~1
if not defined str ( echo Empty string )

Ce code générera "Chaîne vide" si% 1 est soit "" ou "ou vide. L'ajouté à la réponse acceptée qui est actuellement incorrecte.

2
GrayFace

En utilisant ! au lieu de "pour vérifier une chaîne vide

@echo off
SET a=
SET b=Hello
IF !%a%! == !! echo String a is empty
IF !%b%! == !! echo String b is empty
0
Lin W

J'ai eu beaucoup de problèmes avec beaucoup de réponses sur le net. La plupart fonctionnent pour la plupart des choses, mais il y a toujours un cas qui casse chacun d'eux.
Peut-être que ça ne marche pas s'il y a des guillemets, peut-être qu'il casse s'il n'y a pas de guillemets, une erreur de syntaxe si la var a un espace, certains ne fonctionneront que sur des paramètres (par opposition aux variables d'environnement), d'autres techniques permet à un ensemble vide de guillemets de passer comme "définis", et certains plus délicats ne vous laisseront pas enchaîner une else par la suite.

Voici une solution qui me convient, faites-le-moi savoir si vous trouvez un coin qui ne fonctionnera pas.

:ifSet
if "%~1"=="" (Exit /B 1) else (Exit /B 0)

Avoir ce sous-programme soit dans votre script, soit dans son propre .bat, devrait fonctionner.
Donc si vous vouliez écrire (en pseudo):

if (var)
then something
else somethingElse

Tu peux écrire:

(Call :ifSet %var% && (
    Echo something
)) || (
    Echo something else
)

Cela a fonctionné pour tous mes tests:

(Call :ifSet && ECHO y) || ECHO n
(Call :ifSet a && ECHO y) || ECHO n
(Call :ifSet "" && ECHO y) || ECHO n
(Call :ifSet "a" && ECHO y) || ECHO n
(Call :ifSet "a a" && ECHO y) || ECHO n

Écho n, y, n, y, y


Plus d'exemples:

  • Vous voulez juste vérifier if? Call :ifSet %var% && Echo set
  • Juste si non (seulement le reste)? Call :ifSet %var% || Echo set
  • Vérifier un argument passé; fonctionne bien. Call :ifSet %1 && Echo set
  • Vous ne voulez pas encombrer vos scripts/code dupe, vous le mettez donc dans son propre ifSet.bat? Pas de problème: ((Call ifSet.bat %var%) && Echo set) || (Echo not set)
0
Hashbrown

Je suis arrivé il y a un peu moins d'un mois (même si cela avait été demandé il y a 8 ans) ... J'espère qu'il/elle est maintenant passé au-delà des fichiers de traitement par lots. ; -) Je faisais ça tout le temps. Je ne suis cependant pas sûr de l'objectif ultime. S'il est paresseux comme moi, mon go.bat fonctionne pour des choses comme ça. (Voir ci-dessous) Mais, 1, la commande de l'OP peut ne pas être valide si vous utilisez directement l'entrée en tant que commande. c'est à dire., 

"C:/Users/Me"

est une commande invalide (ou utilisée si vous étiez sur un autre lecteur). Vous devez le diviser en deux parties.

C:
cd /Users/Me

Et, 2, que signifie "défini" ou "non défini"? GIGO. J'utilise le défaut pour attraper les erreurs. Si l'entrée n'est pas interceptée, elle passe à l'aide (ou à une commande par défaut). Donc, aucune entrée n'est pas une erreur. Vous pouvez essayer de cd à l'entrée et attraper l'erreur s'il y en a une. (Ok, en utilisant go "téléchargements (un seul paren) est récupéré par DOS. (Harsh!))

cd "%1"
if %errorlevel% neq 0 goto :error

Et, 3, les guillemets sont nécessaires uniquement autour du chemin, pas de la commande. c'est à dire., 

"cd C:\Users" 

était mauvais (ou utilisé dans le passé) à moins que vous ne soyez sur un autre lecteur. 

cd "\Users" 

est fonctionnel.

cd "\Users\Dr Whos infinite storage space"

fonctionne si vous avez des espaces sur votre chemin. 

@REM go.bat
@REM The @ sigh prevents echo on the current command
@REM The echo on/off turns on/off the echo command. Turn on for debugging
@REM You can't see this.
@echo off
if "help" == "%1" goto :help

if "c" == "%1" C:
if "c" == "%1" goto :done

if "d" == "%1" D:
if "d" == "%1" goto :done

if "home"=="%1" %homedrive%
if "home"=="%1" cd %homepath%
if "home"=="%1" if %errorlevel% neq 0 goto :error
if "home"=="%1" goto :done

if "docs" == "%1" goto :docs

@REM goto :help
echo Default command
cd %1
if %errorlevel% neq 0 goto :error
goto :done

:help
echo "Type go and a code for a location/directory
echo For example
echo go D
echo will change disks (D:)
echo go home
echo will change directories to the users home directory (%homepath%)
echo go pictures
echo will change directories to %homepath%\pictures
echo Notes
echo @ sigh prevents echo on the current command
echo The echo on/off turns on/off the echo command. Turn on for debugging
echo Paths (only) with folder names with spaces need to be inclosed in         quotes (not the ommand)
goto :done

:docs
echo executing "%homedrive%%homepath%\Documents"
%homedrive%
cd "%homepath%\Documents"\test error\
if %errorlevel% neq 0 goto :error
goto :done

:error
echo Error: Input (%1 %2 %3 %4 %5 %6 %7 %8 %9) or command is invalid
echo go help for help
goto :done

:done
0
Xorange