Espace tutos dev’ & informatique 🐧

Gestion des arguments dans les scripts BAT de Windows

Publié le
Article sur le passage des arguments nommés à un script BAT de Windows

Introduction

Quittons un instant le monde du développement web pour nous intéresser aux scripts batch. Ces fichiers texte avec extension .bat sont pratiques pour automatiser certaines tâches sous Windows. Par exemple, je m’en sers dans un projet perso de toolchain de génération de fichiers audio et de vidéos basé sur SoX et FFmpeg.

Aujourd’hui on va voir comment traiter les paramètres passés à un script batch en ligne de commande. Cela permet de rendre le comportement des scripts personnalisable sans avoir à les modifier à chaque fois, un rêve de développeur 🤩

Les bases de la lecture des arguments en batch

Récupérer les arguments par leur index

Commençons par les bases ! La récupération des arguments passés à un script s’effectue en utilisant %1..%9 où le chiffre indique l’index de l’argument à récupérer.
Il est aussi possible d’utiliser la forme %~1..%~9 qui retire les éventuels guillemets doubles qui délimitent les arguments.
Enfin, la valeur spéciale %* correspond à la chaine de l’ensemble des arguments passés au script :

Exemple d’appelArguments
script.bat jean louis dupont%1 = jean , %~1 = jean
%2 = louis , %~2 = louis
%3 = dupont , %~3 = dupont
%* = jean louis dupont
script.bat "jean louis" "dupont"%1 = "jean louis" , %~1 = jean louis
%2 = "dupont", %~2 = dupont
%* = "jean louis" "dupont"
script.bat /param valeur /param2 ""%1 = /param , %~1 = /param
%2 = valeur , %~2 = valeur
%3 = /param2 , %~3 = /param2
%4 = "" , %~4 = (vide)
%* = /param valeur /param2 ""
Appels batch et arguments associés

Dépasser la limite des 9 paramètres

On peut lire les arguments après le neuvième en utilisant la commande shift qui décale de 1 les arguments : le premier argument se retrouve avec la valeur du second, le second avec celle du troisième, le neuvième avec celle du dixième… Il n’y a ainsi pas de limite au nombre de paramètres que l’on peut récupérer.

rem On lit les 9 premiers arguments
set param1=%~1
set param2=%~2
rem ...
set param8=%~8
set param9=%~9

rem On shift pour lire les arguments suivants
shift
set param10=%~9
shift
set param11=%~9

Tester si un argument est vide (ou non)

Pour tester si un argument est vide, on utilise une instruction if en encadrant la valeur %1..%9 avec des crochets [].

rem Test d'existence d'argument
if not [%1]==[] echo L'argument 1 existe

rem Test de non-existence d'argument
if [%1]==[] echo L'argument 1 n'existe pas

La vérification d’existence ne peut se faire qu’avec la forme %1..%9 (et non %~1..%~9) car techniquement une chaine vide entourée de guillemets doubles est un argument valide (ex : script.bat "").

La présence potentielle de guillemets doubles dans la valeur de %1..%9 rend l’encadrement « classique » dans le if avec des guillemets doubles impossible, car cela pourrait causer une erreur (if ""valeur""=="" est invalide). L’utilisation des crochets est quant à elle beaucoup plus sûre.

Le passage des arguments aux fonctions batch

Pour passer des arguments aux fonctions il faut encadrer les arguments par des guillemets doubles pour ne pas avoir de problème si des espaces sont présents. A part ça, récupérer les arguments depuis une fonction se fait exactement comme pour récupérer les arguments du script lui-même, c’est à dire via %1..%9 ou %~1..%~9:

rem Appels de fonction
set param1=Jean Marc
set param2=Des Peupliers
rem INCORRECT - Les espaces posent problème
call :hello_world %param1% %param2%
rem CORRECT - Les double quotes contiennent les espaces 
call :hello_world "%param1%" "%param2%"
goto :eof

rem Fonction qui dit bonjour
rem :hello_world "prenom" "nom"
:hello_world
setlocal
set prenom=%~1
set nom=%~2
echo Bonjour %prenom% %nom%
endlocal
exit /b

Fonction de lecture par index des arguments du script

Faire une fonction d’accès indexé aux arguments du script BAT

On en sait désormais assez pour coder une fonction réutilisable de lecture des arguments passés à un script batch par leur index ! Cela nous permettra de gérer les appels de scripts du genre de :

afficher.bat doc1.txt doc2.txt doc3.txt

N’ayez pas peur, il ne s’agit que d’utiliser les quelques bases que l’on a vues plus haut 😇

Implémentation de la fonction de récupération par index

En utilisant la commande shift en boucle et en testant si le premier argument est vide, il est possible de trouver le nombre d’arguments et de tous les récupérer quel qu’en soit le nombre.

Le code suivant propose une fonction réutilisable :parse_script_arguments qui place dans des variables PARAM_n les valeurs des arguments selon leur index, et dans PARAM_COUNT le nombre d’arguments total.

@echo off

rem Lecture des paramètres du script
call :parse_script_arguments %*

rem Affichage des paramètres passés
echo Vous avez passé %PARAM_COUNT% arguments
for /L %%i IN (1,1,%PARAM_COUNT%) do call echo Argument %%i : %%PARAM_%%i%% 
pause
goto :eof

rem Lecture séquentielle des arguments (PARAM_N=valeur, N de 1 à PARAM_COUNT)
rem :parse_script_arguments %*
:parse_script_arguments
set PARAM_COUNT=0
:parse_script_arguments_loop
if [%1]==[] goto parse_script_arguments_done
set /a PARAM_COUNT=%PARAM_COUNT%+1
set PARAM_%PARAM_COUNT%=%~1
shift
goto parse_script_arguments_loop
:parse_script_arguments_done
exit /b

Quelques retours de la fonction d’accès indexé aux paramètres

Voici des exemples des valeurs retournées par la fonction pour l’accès indexé :

Exemple d’appelRetours
afficher.bat doc1.txt doc2.txt doc3.txt%PARAM_COUNT% = 3
%PARAM_1% = doc1.txt
%PARAM_2% = doc2.txt
%PARAM_3% = doc3.txt
script.bat "jean louis" "" "dupont"%PARAM_COUNT% = 3
%PARAM_1% = jean louis
%PARAM_2% = (vide)
%PARAM_3% = dupont
Retours de :parse_script_arguments (accès par index)

Fonction de lecture par nom des paramètres du script

Faire une fonction d’accès aux arguments nommés du script BAT

Accéder aux paramètres du script par leur index nous rend dépendants de l’ordre de ces derniers. Ce n’est pas un problème quand tous les arguments ont le même rôle, par exemple :

afficher.bat doc1.txt doc2.txt doc3.txt

Par contre, si les paramètres ont un rôle différent, l’appel devient illisible. Pas évident de deviner ce que fait cette commande par exemple :

imprimer.bat doc1.txt 2 1 0

La solution est d’utiliser des arguments nommés (ex : /param valeur). Considérez combien l’appel précédent devient évident sous cette forme :

imprimer.bat /file doc1.txt /hmargin 2 /vmargin 1 /quality 0

Batch ne propose pas de mécanisme natif pour faire cela, mais qu’à cela ne tienne, nous en savons assez pour l’implémenter nous-mêmes 😎

Implémentation de la fonction de récupération par nom

Coder une telle fonction consiste à mettre en place une machine à états. Si un argument du script commence par un slash, alors on est en train de lire un nom. Sinon, il s’agit d’une valeur à associer au nom que l’on a lu précédemment. Pour finir, on garde la logique de boucler et d’utiliser shift tant que le premier argument n’est pas vide.

Le code suivant présente la version d’accès par nom de :parse_script_arguments. Elle place dans des variables PARAM_nom la valeur de chaque argument nommé.

@echo off

rem Lecture des paramètres du script
call :parse_script_arguments %*

rem Gestion de /help
if not "%PARAM_help%"=="" (
  echo Usage : script.bat /prenom "prenom" /nom "nom"
  pause
  goto :eof
)

rem Bonjour /prenom /nom
set hello=Bonjour
if not "%PARAM_prenom%"=="" set hello=%hello% %PARAM_prenom%
if not "%PARAM_nom%"=="" set hello=%hello% %PARAM_nom%
echo %hello%
pause
goto :eof

rem Lecture des arguments nommés (/nom valeur :: PARAM_nom=valeur)
rem :parse_script_arguments %*
:parse_script_arguments
set param=
set paramName=
set paramValue=
:parse_script_arguments_loop
if [%1]==[] goto parse_script_arguments_done
set param=%~1
if "%param%"=="" goto parse_script_arguments_parse_value
if "%param%"=="/" goto parse_script_arguments_parse_value
if "%param:~0,1%"=="/" goto parse_script_arguments_parse_name
goto parse_script_arguments_parse_value
:parse_script_arguments_parse_name
set paramName=%param:~1%
set paramValue=
set PARAM_%paramName%=1
shift
goto parse_script_arguments_loop
:parse_script_arguments_parse_value
if not defined paramValue (
  set paramValue=%param%
) else (
  set paramValue=%paramValue% %param%
)
if defined paramName set PARAM_%paramName%=%paramValue%
shift
goto parse_script_arguments_loop
:parse_script_arguments_done
set param=
set paramName=
set paramValue=
exit /b

💡  La fonction est assez maligne pour gérer l’absence de valeur pour un paramètre nommé (ex : /help), plaçant dans ce cas la valeur à 1 (un flag en quelque sorte). Elle gère aussi l’absence de guillemets doubles dans les valeurs (ex : /prenom jean marc).

Quelques retours de la fonction d’accès aux paramètres nommés

Voici des exemples des valeurs retournées par la fonction pour l’accès aux arguments nommés :

Exemple d’appelRetours
imprimer.bat /file doc1.txt /hmargin 2
/vmargin 1 /quality 0
%PARAM_file% = doc1.txt
%PARAM_hmargin% = 2
%PARAM_vmargin% = 1
%PARAM_quality% = 0
script.bat /help%PARAM_help% = 1
script.bat /test "" /prenom jean louis
/nom "dupont"
%PARAM_test% = (vide)
%PARAM_prenom% = jean louis
%PARAM_nom% = dupont
Retours de :parse_script_arguments (accès par nom)

Gérer le glissé-déposé d’un fichier sur un script BAT

Peu de gens le savent, mais il est possible de glisser-déposer (drag-and-drop) un fichier sur un script batch depuis l’explorateur Windows :

Glisser-déposer un fichier texte sur un script BAT
Le glissé-déposé sur script batch, vous connaissiez ?

C’est un moyen facile pour appeler le script avec en paramètre le chemin du fichier que l’on a déposé. On peut alors l’utiliser comme n’importe quel argument.

@echo off

rem Récupération du fichier déposé
set fichier=%~1

rem Cas ou aucun fichier n'a été passé
if "%fichier%"=="" (
  echo Glissez-déposez un fichier sur le script SVP
  pause
  goto :eof
)

rem Affichage du contenu du fichier
echo Voici le contenu de %fichier% :
type "%fichier%"
pause
goto :eof

💡  Notez l’utilisation des guillemets doubles lors de l’appel à une commande avec en paramètre le fichier qui a été déposé. On ne sait jamais, il pourrait y avoir des espaces dans le chemin ou le nom du fichier !

Conclusion

Le passage de paramètres aux scripts batch n’a désormais plus de secrets pour vous 😉
N’hésitez pas à réutiliser les fonctions de lecture des arguments décrites ici dans vos propres projets d’automatisation Windows, cela vous permettra de vous focaliser sur le code métier à la place.

Bon code à vous, à bientôt pour un autre article !
Je suis joignable depuis la page de contact du site si vous avez besoin de plus de précisions.

Photo de profil de Loïc Burtin Code Colibri développeur web à Dijon

A propos de l'auteur

Loïc Burtin

Développeur web indépendant, avec une tendance à couper les plumes en quatre pour que les sites se chargent plus rapidement.

Partagez cet article  =>