Comment puis-je passer des paramètres de ligne de commande à un fichier batch?
J'ai besoin de passer l'id et le mot de passe à un fichier cmd (ou bat) au moment de l'exécution plutôt que de les coder en dur dans le fichier.
Voici à quoi ressemble la ligne de commande:
test.cmd admin P@55w0rd > test-log.txt
15 réponses
Une Autre astuce utile est d'utiliser %*
pour dire "tous". Par exemple:
echo off
set arg1=%1
set arg2=%2
shift
shift
fake-command /u %arg1% /p %arg2% %*
Lorsque vous exécutez:
test-command admin password foo bar
Le fichier batch ci-dessus s'exécutera:
fake-command /u admin /p password foo bar
J'ai peut-être la syntaxe un peu mal, mais c'est l'idée générale.
Voici comment je le fais.
@fake-command /u %1 /p %2
Voici à quoi ressemble la ligne de commande:
test.cmd admin P@55w0rd > test-log.txt
Le %1 s'applique au premier paramètre le %2 (et voici la partie délicate) s'applique au second. Vous pouvez avoir jusqu'à 9 paramètres passés de cette façon.
Si vous voulez gérer intelligemment les paramètres manquants, vous pouvez faire quelque chose comme:
IF %1.==. GOTO No1
IF %2.==. GOTO No2
... do stuff...
GOTO End1
:No1
ECHO No param 1
GOTO End1
:No2
ECHO No param 2
GOTO End1
:End1
L'accès aux paramètres de lot peut être simple avec %1, %2, ... %9 ou aussi %*,
mais seulement si le contenu est simple.
Il N'y a pas de moyen simple pour des contenus complexes comme "&"^&
, car il n'est pas possible d'accéder à %1 sans générer une erreur.
set var=%1
set "var=%1"
set var=%~1
set "var=%~1"
Les lignes s'étendent à
set var="&"&
set "var="&"&"
set var="&"&
set "var="&"&"
Et chaque ligne échoue, car l'un des &
est en dehors des guillemets.
Il peut être résolu en lisant à partir d'un fichier temporaire une versionremarquée du paramètre.
@echo off
SETLOCAL DisableDelayedExpansion
SETLOCAL
for %%a in (1) do (
set "prompt="
echo on
for %%b in (1) do rem * #%1#
@echo off
) > param.txt
ENDLOCAL
for /F "delims=" %%L in (param.txt) do (
set "param1=%%L"
)
SETLOCAL EnableDelayedExpansion
set "param1=!param1:*#=!"
set "param1=!param1:~0,-2!"
echo %%1 is '!param1!'
L'astuce consiste à activer echo on
et à développer le %1 après une instruction rem
(fonctionne également avec %2 .. %*
).
Ainsi, même "&"&
pourrait être repris sans produire d'erreur, comme on le remarque.
Mais pour pouvoir rediriger la sortie du echo on
, vous avez besoin des deux boucles for.
, Les caractères supplémentaires * #
sont utilisés pour être en sécurité contre des contenus comme /?
(montrerait l'aide de REM
).
Ou un caret ^ à la fin de la ligne pourrait fonctionner comme une multiligne caractère, même après un rem
.
Puis en lisant le paramètre rem sortie du fichier, mais soigneusement.
LE FOR / F devrait fonctionner avec une expansion retardée, sinon le contenu avec"!"serait détruit.
Après avoir supprimé les caractères supplémentaires dans param1
, Vous l'avez.
Et pour utiliser param1
de manière sûre, activez l'expansion retardée.
Oui, et n'oubliez pas d'utiliser des variables comme %%1
lorsque vous utilisez if
et for
et le gang.
Si vous oubliez le double %
, vous substituerez des arguments de ligne de commande (éventuellement null) et vous recevrez des messages d'erreur assez confus.
Il n'y a pas besoin de le compliquer. C'est simplement la commande %1 %2 paramètres, par exemple,
@echo off
xcopy %1 %2 /D /E /C /Q /H /R /K /Y /Z
echo copied %1 to %2
pause
La "pause" affiche ce que le fichier batch a fait et attend que vous frappiez la touche ANY. Enregistrez-le sous xx. bat dans le dossier Windows.
Pour l'utiliser, tapez, par exemple:
xx c:\f\30\*.* f:\sites\30
Ce fichier batch prend en charge tous les paramètres nécessaires, comme la copie uniquement des fichiers, qui sont plus récents, etc. Je l'ai utilisé depuis avant Windows. Si vous aimez voir les noms des fichiers, comme ils sont copiés, omettez le paramètre Q
.
@ECHO OFF
:Loop
IF "%1"=="" GOTO Continue
SHIFT
GOTO Loop
:Continue
Remarque: Si {[1] } causera des problèmes si %1
est entre guillemets lui-même.
Dans ce cas, utilisez IF [%1]==[]
ou, dans NT 4 (SP6) et versions ultérieures seulement, IF "%~1"==""
à la place.
Un ami me posait des questions sur ce sujet récemment, alors j'ai pensé poster comment je gère les arguments de ligne de commande dans les fichiers batch.
Cette technique a un peu de surcharge comme vous le verrez, mais elle rend mes fichiers batch très faciles à comprendre et rapides à mettre en œuvre. Ainsi que de soutenir les structures suivantes:
>template.bat [-f] [--flag] [/f] [--namedvalue value] arg1 [arg2][arg3][...]
Le jist de c'est d'avoir la :init
, :parse
, et :main
fonctions.
Exemple d'utilisation
>template.bat /?
test v1.23
This is a sample batch file template,
providing command-line arguments and flags.
USAGE:
test.bat [flags] "required argument" "optional argument"
/?, --help shows this help
/v, --version shows the version
/e, --verbose shows detailed output
-f, --flag value specifies a named parameter value
>template.bat <- throws missing argument error
(same as /?, plus..)
**** ****
**** MISSING "REQUIRED ARGUMENT" ****
**** ****
>template.bat -v
1.23
>template.bat --version
test v1.23
This is a sample batch file template,
providing command-line arguments and flags.
>template.bat -e arg1
**** DEBUG IS ON
UnNamedArgument: "arg1"
UnNamedOptionalArg: not provided
NamedFlag: not provided
>template.bat --flag "my flag" arg1 arg2
UnNamedArgument: "arg1"
UnNamedOptionalArg: "arg2"
NamedFlag: "my flag"
>template.bat --verbose "argument #1" --flag "my flag" second
**** DEBUG IS ON
UnNamedArgument: "argument #1"
UnNamedOptionalArg: "second"
NamedFlag: "my flag"
Modèle.MTD
@::!/dos/rocks
@echo off
goto :init
:header
echo %__NAME% v%__VERSION%
echo This is a sample batch file template,
echo providing command-line arguments and flags.
echo.
goto :eof
:usage
echo USAGE:
echo %__BAT_NAME% [flags] "required argument" "optional argument"
echo.
echo. /?, --help shows this help
echo. /v, --version shows the version
echo. /e, --verbose shows detailed output
echo. -f, --flag value specifies a named parameter value
goto :eof
:version
if "%~1"=="full" call :header & goto :eof
echo %__VERSION%
goto :eof
:missing_argument
call :header
call :usage
echo.
echo **** ****
echo **** MISSING "REQUIRED ARGUMENT" ****
echo **** ****
echo.
goto :eof
:init
set "__NAME=%~n0"
set "__VERSION=1.23"
set "__YEAR=2017"
set "__BAT_FILE=%~0"
set "__BAT_PATH=%~dp0"
set "__BAT_NAME=%~nx0"
set "OptHelp="
set "OptVersion="
set "OptVerbose="
set "UnNamedArgument="
set "UnNamedOptionalArg="
set "NamedFlag="
:parse
if "%~1"=="" goto :validate
if /i "%~1"=="/?" call :header & call :usage "%~2" & goto :end
if /i "%~1"=="-?" call :header & call :usage "%~2" & goto :end
if /i "%~1"=="--help" call :header & call :usage "%~2" & goto :end
if /i "%~1"=="/v" call :version & goto :end
if /i "%~1"=="-v" call :version & goto :end
if /i "%~1"=="--version" call :version full & goto :end
if /i "%~1"=="/e" set "OptVerbose=yes" & shift & goto :parse
if /i "%~1"=="-e" set "OptVerbose=yes" & shift & goto :parse
if /i "%~1"=="--verbose" set "OptVerbose=yes" & shift & goto :parse
if /i "%~1"=="--flag" set "NamedFlag=%~2" & shift & shift & goto :parse
if not defined UnNamedArgument set "UnNamedArgument=%~1" & shift & goto :parse
if not defined UnNamedOptionalArg set "UnNamedOptionalArg=%~1" & shift & goto :parse
shift
goto :parse
:validate
if not defined UnNamedArgument call :missing_argument & goto :end
:main
if defined OptVerbose (
echo **** DEBUG IS ON
)
echo UnNamedArgument: "%UnNamedArgument%"
if defined UnNamedOptionalArg echo UnNamedOptionalArg: "%UnNamedOptionalArg%"
if not defined UnNamedOptionalArg echo UnNamedOptionalArg: not provided
if defined NamedFlag echo NamedFlag: "%NamedFlag%"
if not defined NamedFlag echo NamedFlag: not provided
:end
call :cleanup
exit /B
:cleanup
REM The cleanup function is only really necessary if you
REM are _not_ using SETLOCAL.
set "__NAME="
set "__VERSION="
set "__YEAR="
set "__BAT_FILE="
set "__BAT_PATH="
set "__BAT_NAME="
set "OptHelp="
set "OptVersion="
set "OptVerbose="
set "UnNamedArgument="
set "UnNamedArgument2="
set "NamedFlag="
goto :eof
Restons simples.
Voici le .fichier cmd.
@echo off
rem this file is named echo_3params.cmd
echo %1
echo %2
echo %3
set v1=%1
set v2=%2
set v3=%3
echo v1 equals %v1%
echo v2 equals %v2%
echo v3 equals %v3%
Voici 3 appels de la ligne de commande.
C:\Users\joeco>echo_3params 1abc 2 def 3 ghi
1abc
2
def
v1 equals 1abc
v2 equals 2
v3 equals def
C:\Users\joeco>echo_3params 1abc "2 def" "3 ghi"
1abc
"2 def"
"3 ghi"
v1 equals 1abc
v2 equals "2 def"
v3 equals "3 ghi"
C:\Users\joeco>echo_3params 1abc '2 def' "3 ghi"
1abc
'2
def'
v1 equals 1abc
v2 equals '2
v3 equals def'
C:\Users\joeco>
FOR %%A IN (%*) DO (
REM Now your batch file handles %%A instead of %1
REM No need to use SHIFT anymore.
ECHO %%A
)
Cette boucle sur les paramètres de lot ( % * ) soit ils sont entre guillemets ou non, puis échos chaque paramètre.
J'ai écrit un script read_params simple qui peut être appelé en tant que Fonction (Ou Externe .bat
) et mettra toutes les variables dans l'environnement actuel. Il ne modifiera pas les paramètres d'origine car la fonction est call
ed avec une copie des paramètres d'origine.
Par exemple, avec la commande suivante:
myscript.bat some -random=43 extra -greeting="hello world" fluff
myscript.bat
serait capable d'utiliser les variables après avoir appelé la fonction:
call :read_params %*
echo %random%
echo %greeting%
Voici le fonction:
:read_params
if not %1/==/ (
if not "%__var%"=="" (
if not "%__var:~0,1%"=="-" (
endlocal
goto read_params
)
endlocal & set %__var:~1%=%~1
) else (
setlocal & set __var=%~1
)
shift
goto read_params
)
exit /B
Limites
- impossible de charger des arguments sans valeur tels que
-force
. Vous pouvez utiliser-force=true
mais je ne peux pas penser à un moyen d'autoriser des valeurs vides sans connaître une liste de paramètres à l'avance qui n'auront pas de valeur.
Changelog
-
2/18/2016
- ne nécessite plus d'expansion retardée
- fonctionne maintenant avec d'autres arguments de ligne de commande en recherchant
-
avant de paramètres.
Pour faire référence à une variable set en ligne de commande, vous devez utiliser " % a%", par exemple:
set a=100
echo %a%
output = 100
Remarque: cela fonctionne pour Windows 7 pro.
Créer un nouveau fichier batch (exemple: openclass.bat) et écrivez cette ligne dans le fichier:
java %~n1
, Puis placez le fichier batch dans, disons, le dossier system32, allez dans votre fichier de classe Java, clic droit, Propriétés, Ouvrez avec..., puis Trouvez votre fichier batch, sélectionnez-le et c'est tout...
Ça marche pour moi.
PS: Je ne trouve pas de moyen de fermer la fenêtre cmd lorsque je ferme la classe Java. Pour l'instant...
Solution Simple (même si la question Est ancienne)
Essai1.MTD
echo off
echo "Batch started"
set arg1=%1
echo "arg1 is %arg1%"
echo on
pause
CallTest1.MTD
call "C:\Temp\Test1.bat" pass123
Sortie
YourLocalPath>call "C:\Temp\test.bat" pass123
YourLocalPath>echo off
"Batch started"
"arg1 is pass123"
YourLocalPath>pause
Press any key to continue . . .
Où YourLocalPath est le chemin du répertoire courant.
Pour garder les choses simples, stockez le paramètre de commande dans variable et utilisez variable pour la comparaison.
Ce n'est pas seulement simple à écrire, mais c'est aussi simple à maintenir, donc si plus tard une autre personne ou vous lisez votre script après une longue période de temps, il sera facile à comprendre et maintenir.
Pour écrire du code en ligne: voir d'autres réponses.
Inspiré par une réponse ailleurs par @Jon, j'ai conçu un algorithme plus général pour extraire les paramètres nommés, les valeurs optionnelles et les commutateurs.
Disons que nous voulons implémenter un utilitaire foobar
. Il nécessite une commande initiale. C'est un paramètre facultatif --foo
un optionnel valeur (qui ne peut pas être un autre paramètre, bien sûr); si la valeur par défaut default
. Il a également un paramètre optionnel --bar
qui prend un valeur requise . Enfin, il peut prendre un drapeau --baz
sans valeur autorisée. Oh, et ces paramètres peuvent venir dans n'importe quel ordre.
En d'autres termes, cela ressemble à ceci:
foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]
Voici une solution:
@ECHO OFF
SETLOCAL
REM FooBar parameter demo
REM By Garret Wilson
SET CMD=%~1
IF "%CMD%" == "" (
GOTO usage
)
SET FOO=
SET DEFAULT_FOO=default
SET BAR=
SET BAZ=
SHIFT
:args
SET PARAM=%~1
SET ARG=%~2
IF "%PARAM%" == "--foo" (
SHIFT
IF NOT "%ARG%" == "" (
IF NOT "%ARG:~0,2%" == "--" (
SET FOO=%ARG%
SHIFT
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE IF "%PARAM%" == "--bar" (
SHIFT
IF NOT "%ARG%" == "" (
SET BAR=%ARG%
SHIFT
) ELSE (
ECHO Missing bar value. 1>&2
ECHO:
GOTO usage
)
) ELSE IF "%PARAM%" == "--baz" (
SHIFT
SET BAZ=true
) ELSE IF "%PARAM%" == "" (
GOTO endargs
) ELSE (
ECHO Unrecognized option %1. 1>&2
ECHO:
GOTO usage
)
GOTO args
:endargs
ECHO Command: %CMD%
IF NOT "%FOO%" == "" (
ECHO Foo: %FOO%
)
IF NOT "%BAR%" == "" (
ECHO Bar: %BAR%
)
IF "%BAZ%" == "true" (
ECHO Baz
)
REM TODO do something with FOO, BAR, and/or BAZ
GOTO :eof
:usage
ECHO FooBar
ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1
- utilisez
SETLOCAL
pour que les variables ne s'échappent pas dans l'environnement appelant. - N'oubliez pas d'initialiser les variables
SET FOO=
, etc. dans le cas où quelqu'un les a définis dans l'environnement appelant. - utilisez
%~1
pour supprimer citation. - utilisez
IF "%ARG%" == ""
et nonIF [%ARG%] == []
parce que[
et]
ne jouent pas du tout avec des valeurs se terminant dans un espace. - même si vous
SHIFT
à l'intérieur d'un blocIF
, les arguments actuels tels que%~1
ne sont pas mis à jour car ils sont déterminés lorsque leIF
est analysé. Vous pouvez utiliser%~1
et%~2
à l'intérieur du blocIF
, mais ce serait déroutant parce que vous aviez unSHIFT
. Vous pouvez mettre leSHIFT
à la fin du bloc pour plus de clarté, mais cela pourrait se perdre et / ou confondre les gens ainsi. Donc, "capturer"%~1
et%~1
en dehors du bloc semble le meilleur. - Vous ne voulez pas utiliser un paramètre à la place de la valeur optionnelle d'un autre paramètre, vous devez donc vérifier
IF NOT "%ARG:~0,2%" == "--"
. - attention seulement à
SHIFT
{lorsque vous[41]}utiliser l'un des paramètres. - Le code en double
SET FOO=%DEFAULT_FOO%
est regrettable, mais l'autre solution serait d'ajouter unIF "%FOO%" == "" SET FOO=%DEFAULT_FOO%
dehors de laIF NOT "%ARG%" == ""
bloc. Cependant, comme cela se trouve toujours dans le blocIF "%PARAM%" == "--foo"
, la valeur%FOO%
aurait été évalué et défini avant d'entrer dans le bloc, de sorte que vous ne détecterez jamais que les deux le paramètre--foo
était présent et aussi que la valeur%FOO%
était manquante. - notez que
ECHO Missing bar value. 1>&2
envoie le message d'erreur à stderr. - Vous voulez une ligne vide dans un fichier batch Windows? Tu dois utiliser
ECHO:
ou l'une des variantes.