Batch est LE langage de script originel de MS/DOS, puis Windows. Son but primitif est d'enchaîner des commandes (de les exécuter les unes à la suite des autres). Cependant, et contrairement à des idées reçues, Batch a continué à évoluer, au fil des versions de Windows. De plus, il bénéficie du développement des nombreuses commandes de Windows, ou des améliorations de ces commandes. Ci-dessous, vous trouverez une introduction assez complète au Batch. Des exemples (menu de gauche) vous aideront à assimiler le Batching Enfin, des utilitaires vous permettront d'aller plus loin. Ce site en est français Avertissement : Azo-3 m'ayant fait remarquer que, en anglais, le pluriel de "batch", c'est "batches", je tiens à préciser que, dans ce site, j'utilise "batch" en tant que mot français. Son pluriel devient donc "batchs". A bon entendeur, salut !
Préambule Le batch (traitement par lots, en français) est le fondement du scripting. La version MS/DOS du batch a été matérialisée sous forme de fichiers ".BAT". Elle a été assez connue, et largement utilisée. L’arrivée de Windows n’a pas fait disparaître ces fonctionnalités. Et chaque version de Windows a apporté son lot d’améliorations et d’extensions. Le résultat, c’est que les batchs, sous Windows-Vista (ou XP) sont devenus plus souples, et peuvent utiliser des commandes très puissantes, trop souvent ignorées des utilisateurs, même chevronnés.
Introduction Les pages de ce site ne cherchent pas à être exhaustives, mais vous propose un voyage de (re)-découverte, dans les contrées étonnantes du scripting primordial que constituent les batchs.
Utilisation de ce site (de cette page) Le mieux, c’est de créer un répertoire (je suggère C:\Dev\Bat), pour y enregistrer les exemples. Ensuite, ce site est un espace non-fumeur. Veuillez ne pas fumer, lorsque vous consulter ce site. En plus de votre santé, il ne faut pas oublier le fond de page, en bois, qui pourrait prendre feu...
Périmètre On ne causera, ici, que du scripting de Windows, Vista et XP. L’essentiel portera sur le fonctionnement en "invite de commande", par le biais d’exemples "basiques", et d’explications succintes. Notons que Microsoft, au lieu de batch, parle de fichier de commandes, et utilise un vocabulaire légèrement différent du mien. Mais vous devriez vous y retrouver. Allez, on démarre..
Tutorial Début Le scripting en batch commence par l'utilisation des suites de commandes, regroupées dans un fichier dont l’extension est ".BAT". (on peut aussi utiliser d'autres extensions, comme .CMD mais cela revient au même) Exemple : Lancez l’Invite de Commande (Programmes, Accessoires, Invite de Commande) Allez à la racine du disque C: (tapez : CD /DC:\ {Entrée} ) Tapez Notepad [Entrée] Saisissez le texte suivant (ou faites du copier/coller) : C: CD \ MD DEV CD DEV MD BAT CD BAT
Faites, par le menu, Fichier + Enregistrer, et tapez C:\TOTO.BAT Validez. Dans l’Invite de commande, tapez TOTO {Entrée} Ôh ! Miracle ! La suite des commandes s’est exécutée de façon automatique. Vous avez compris ? Alors, vous êtes maintenant BETE (Batch Etudiant Très Emu). Et, cela mérite bien une petite récompense :
Aide sur des commandes utilisables. Dans l’invite de commande, tapez HELP | MORE /E [Entrée] (note : pour passer à la page suivante, appuyez sur [Espace] ; pour quitter, appuyez sur Q ) Cela vous donnera une liste des commandes fournies avec Windows. Pour la plupart de ces commandes, vous pourrez obtenir une aide spécifique, En faisant suivant le nom de la commande par "/?". Par exemple : DIR /? Toutes les commandes de Windows ne sont pas listées. Il manque, par exemple : FTP NET NETSTAT WMIC ou tous les outils externes ou additionnels.
Ruptures du fonctionnement séquentiel Dans les fichiers batchs, les commandes s’exécutent les unes à la suite des autres. Mais il est possible de changer ce fonctionnement, grâce aux commandes : Rappel : pour obtenir une aide, faites suivre la commande par "/?". Exemple : IF /? Nous verrons, un peu plus loin quelques exemples d’utilisation de ces commandes.
Variables Les variables sont repérées de 3 façons, similaires à ces 3 exemples : - %TOTAL% (variable habituelle)
- %1 (variable d’argument, lecture seule)
- %%i (variable de la commande FOR)
Pour affecter une variable, on utilise SET. Pour la visualiser, ECHO. Essayez cet exemple (b01.bat) : @ECHO OFF SET var1=ABC DEF ECHO %var1% SET var2=123%var1%456 echo %var2% Attention, TOUS les caractères peuvent être importants. Par exemple, la ligne SET var1=ABC DEF peut très bien se terminer par un, ou des, espace(s), tabulation, etc. Ces caractères seront pris en compte, et peuvent être importants. Alors, veillez à en tenir compte. Il existe des variables prédéfinies (b02.bat) :
@echo off echo Le répertoire courant est %CD% echo Le répertoire temporaire est %TEMP% echo Le répertoire de windows est %WINDIR% echo etc. Les variables batchs ne sont pas typées. Elles ne contiennent que des caractères, et le contenu se termine par un retour chariot. (il est impossible, en batch, d'avoir des contenus de variables multi-lignes ; pour contourner ça, il faut passer par des fichiers utilisés comme des variables). La longueur de leur contenu est suffisant (j’ai testé avec succès des longueur supérieures à 1000 caractères).
Compléments sur l’affectation (b03.bat) : @echo off set A=2 set /A B="(14*3)-(78/2)" set /A C=A+B echo A = %A% echo B = %B% echo C = A+B = %C% REM résultat : C = A+B = 5 Et oui ! On peut faire des calculs dans les batchs. Beaucoup ignorent ça. Le calcul peut aussi être dynamique (b03b.bat) : @echo off set A=2 set B=3 set D="(B+A)-(B-A)" set /A C=%D% echo C=%C% REM résultat : C=4 Anticipons. Le script suivant (b04.bat) calcule la taille des fichiers .BAT du répertoire courant : @echo off set TOTAL=0 set NB=0 for %%i in (*.bat) do ( call :CUMUL %%~zi ) echo Nb fichier : %NB% echo Taille totale : %TOTAL% octets goto :EOF :CUMUL set /A NB+=1 set /A TOTAL+=%1 goto :EOF Vous aurez noté l’utilisation de "+=". Pour plus de détail sur les calculs : SET /? Affectation, encore (b05.bat) : @echo off set A=%1 set B=%2 set C=%* echo %C% set /P I=Identifiez-vous, SVP : :: notez l’espace à la fin de la ligne précédente... echo Vous avez tapé %I% set A=ABCDEF set B=%A:~2,3% echo %B% set C=%A:~-3% echo %C% Sauvez ça dans b05.bat, et lancez par la commande : b05 ABCD 22 33 44 On a, respectivement : - récupéré et affecté l’argument 1 (ABCD) (argument = paramètre) - récupéré et affecté l’argument 2 (22) - récupéré et affecté tous les arguments - saisi, interactivement, une valeur - extrait, et affecté, une partie d’une variable (ABCDEF --> CDE) - extrait, et affecté, les 3 derniers caractères d’une variable (ABCDEF --> DEF) Notez que %0 existe aussi, et que %* représente ici la ligne de commande tapée (en réalité, c’est la commande d’appel, mais la subtilité de la différence des termes n’est pas subtilement différente de la confusion dûe aux différents termes que j’ai subtilisés au vocabulaire français, pour terminer cette phrase d’une manière pas très subtile). Rappel : l’extraction commence au caractère zéro (0). Malheureusement, on ne peut pas utiliser de variable, à l’intérieur de l’extraction d’une partie d’une variable. Ah, le vie est parfois cruelle, n’est-ce pas ? Solution : la vie est belle en batch ! examinez le scripts suivant (b06.bat) : @echo off set A=ABCDEF set B=2 set C=3 echo set D=%%A%:~%B%,%C%%% > %TEMP%\TMP.BAT call %TEMP%\TMP echo %D% :: Résultat : CDE On a bien extrait de A selon le contenu de B et C L’utilisation dynamique du Batch est très intéressante. Et ce n’est pas fini !
Problème de visualisation des accents ? C’est parce que le code-page de votre invite de commande est mal configuré. Essayez de taper la commande suivante : MODE CON: CP SELECT=1252 Puis, éventuellement, changez la police de l’invite de commande, par les propriétés de la fenêtre.
Copier/Coller avec une invite de commande Facile. Il suffit de passer par le menu système de la fenêtre de l’invite de commande (sous-menu "Modifier") Cette astuce, notamment pour "Coller" a été trouvée à Montélimar, dans la Drôme. D’ailleurs, il est connu que la colle de la Drôme adhère... Mais, attention, si je dé-blatère un peu, ne soyez pas trop vache avec moi (ni SVP).
Espace de noms (setlocal) On peut gérer des variables locales. Essayez ce scripts (b06.bat) : @echo off set B=2 set C=3 echo %B% %C% setlocal set B=22 set C=33 echo %B% %C% setlocal set B=222 set C=333 echo %B% %C% endlocal echo %B% %C% endlocal echo %B% %C% Je vous ai assez gonflé avec les variables. Passons à autre chose. IF Explications par l’exemple (b07.bat) : @echo off set A=ABC set B=2 set C=3 set D= echo ------------------------- if %A%==ABC echo A contient ABC if X%D%==X echo D est vide ou n’existe pas if X%E%==X echo E est vide ou n’existe pas if defined C (echo C est une variable existante et affectée) else (echo C n’est pas affectée, ou n’existe pas) if defined D (echo D est une variable existante et affectée) else (echo D n’est pas affectée, ou n’existe pas) if exist b07.bat echo b07.bat est un fichier existant echo - if /i %C% LEQ 22 ( echo C est inférieur ou égal à 22 echo la comparaison est numérique echo Cette ligne, juste pour voir si vous lisez mes exemples ; echo et on peut avoir plusieurs lignes dans chaque commande du IF ) else ( echo C est supérieur à 22 ) echo - if not exist Bis md Bis xcopy /Q bb07.bat Bis > nul if /i %ERRORLEVEL% GEQ 1 ( echo Problème dans la copie ) else ( echo copie effectuée ) echo - echo ------------------------- GOTO
Exemple (b08.bat) : @echo off echo ------------------------------ set A=1 set B=2 set C=3 echo %A% %B% %C% goto SUITE
::cette partie est sautée... set A=11 set B=22 set C=33 :SUITE echo %A% %B% %C% echo ------------------------------ goto ABCDEFGHIJ2
:ABCDEFGHIJ set A=1 set B=2 set C=3 goto SUITE2 :ABCDEFGHIJ2 set A=11 set B=22 set C=33 goto SUITE2 :ABCDEFGHIJ3 set A=111 set B=222 set C=333 goto SUITE2 :SUITE2 echo %A% %B% %C% echo ------------------------------
set ETIQ=ABCD2 goto %ETIQ% :ABCD1 set A=A set B=A set C=A goto SUITE3 :ABCD2 set A=AA set B=AA set C=AA goto SUITE3 :ABCD3 set A=AAA set B=BBB set C=CCC goto SUITE3 :SUITE3 echo %A% %B% %C%
echo ------------------------------ goto :EOF Notes : :EOF est une étiquette prédéfinie, sur la fin du fichier. l’appel peut être dynamique (cf le goto %ETIQ%)
CALL Appel d’un(e partie) sous-programme. L’appel peut faire référence à un fichier externe, ou à une autre partie du même fichier, repérée par une étiquette. Il n’y a pas de return. C’est la fin de fichier qui détermine le RETURN (pensez à GOTO :EOF) Pour des variables locales, rappelez-vous SETLOCAL / ENDLOCAL Exemple (b09a.bat et b09.bat, lancez b09) : b09a.bat : @echo off :: exemple de bibliothèque avec multiples routines if X%1==X goto PASDETIQUETTE set TMP=%1 set TMP=%TMP:~0,1% if %TMP%==: goto ETIQ goto CESTPASUNETIQUETTE goto :EOF :CESTPASUNETIQUETTE echo appel avec un (1er) argument echo qui n’est pas une étiquette goto :EOF :PASDETIQUETTE echo Appel sans argument echo (sans étiquette) goto :EOF :ETIQ GOTO %1 GOTO :EOF
:ASUB1 echo A_Sub_1 goto :EOF
:ASUB2 echo A_Sub_2 goto :EOF
:ASUB3 echo A_Sub_3 ; paramètres %* goto :EOF
:ASUB4 echo A_Sub_4 goto :EOF
b09.bat : @echo off echo --------------------------- call :SUB2 call :SUB3 AA BBB CCCC set ETIQ=:SUB4 call %ETIQ% echo --------------------------- call b09a echo --------------------------- call b09a :ASUB2 echo --------------------------- call b09a AAASUB echo --------------------------- call b09a :ASUB3 111 2222 33333 echo --------------------------- goto FIN :SUB1 echo Sub_1 goto :EOF
:SUB2 echo Sub_2 goto :EOF
:SUB3 echo --------------------------- echo Sub_3 ; paramètres %0 %1 %2 %3 echo tous les paramètres : %* echo --------------------------- goto :EOF
:SUB4 echo Sub_4 goto :EOF
:SUB5 echo Sub_5 goto :EOF
:FIN echo ---------------------------
Notes : Vous aurez remarqué comment le CALL dynamique permet de créer des bibliothèques de routines, et comment on peut les utiliser. Le même CALL dynamique permet de gérer du CallBack. Tout ça, associé à la création de fichier à la volée, donne d’immenses possibilités. Autre point : un CALL sur une étiquette ne fonctionne qu’à l’intérieur du même fichier. Mais vous avez vu comment contourner cette limitation.
Expansion, extension, retard...
L’extension de commandes (les améliorations de Windows-Vista/XP), est activé par défaut. L’extension des variables (ou expansion, ou, plutôt la substitution d’une variable par son contenu) est réalisé à la lecture de chaque ligne, par l’interpréteur de commandes. Toutefois, il est possible d’opter pour "l’expansion retardée". Le remplacement de valeur de fait alors à l’exécution de la ligne. Voir CMD /? pour plus de détails. FOR FOR, c’est fort utile pour boucler. (je n’ai pas FORcé, là...) Les boucles FOR peuvent parcourir plusieurs types d’ensembles : - un ensemble - des ensembles de fichiers - un intervalle numérique (début, pas, fin) - une chaîne - le résultat d’une commande Avant de passer à l’exemple, il faut faire tourner le script suivant (b10a.bat) : @echo off
echo AAAAAAAAAA > abc.txt echo BBBBBBBBBB >> abc.txt echo CCCCCCCCCC >> abc.txt echo DDDDDDDDDD >> abc.txt echo ABCDEFGHIJ > aaa.txt C: CD cd Dev cd bat md Bis md 2 md Bis\bis xcopy *.* 2 xcopy *.bat Bis xcopy *.txt Bis\Bis Et voici l’exemple (b10.bat) :
@echo off ::---- For, fichiers et répertoires echo -R---.----- FOR /R C:\Dev\bat %%i IN (.) DO ( echo %%i ) echo -R---txt--- FOR /R C:\Dev\bat %%i IN (*.txt) DO ( echo %%i ) echo -R---txt--- FOR /R . %%i IN (*.txt) DO ( echo %%i ) echo -D--------- FOR /D %%i IN (*.*) DO ( echo %%i ) echo -F--Dir---- FOR /F "usebackq" %%i IN (`dir /B/S/A:D`) DO ( echo %%i ) echo -R---hiérarchie autre méthode--- FOR /R %%i IN (.) DO ( echo %%~dpni ) echo -R---txt--- FOR /R Bis %%i IN (*.txt) DO ( echo %%i ) echo -R---txt-Date-time--- FOR /R Bis %%i IN (*.txt) DO ( echo %%i %%~ti ) echo -R---txt-Taille--- FOR /R Bis %%i IN (*.txt) DO ( echo %%i %%~zi ) echo -R---txt-Chemin-seul--- FOR /R Bis %%i IN (*.txt) DO ( echo %%i %%~pi ) echo -R---txt-Lecteur--- FOR /R Bis %%i IN (*.txt) DO ( echo %%i %%~di ) echo -R---txt-Nom-complet--- (cf si %xxx% comme %TEMP%) FOR /R Bis %%i IN (*.txt) DO ( echo %%i %%~fi ) echo -R---txt-Fichier seul (san extension)--- FOR /R Bis %%i IN (*.txt) DO ( echo %%i %%~ni ) echo -R---txt-Extension--- FOR /R Bis %%i IN (*.txt) DO ( echo %%i %%~xi ) echo -R---txt-Attributs--- FOR /R Bis %%i IN (*.txt) DO ( echo %%i %%~ai ) echo -R---txt-Lecteur + Chemin-seul--- FOR /R Bis %%i IN (*.txt) DO ( echo %%i %%~dpi ) echo -R---Fichier + Path--- FOR %%i IN (notepad.exe write.exe calc.exe cmd.exe regedit.exe) DO ( echo %%i %%~$PATH:i ) echo ----------- L’exemple est assez complet, pour se suffire à lui-même.
Vous voyez que, avec FOR, il est possible de manipuler facilement des ensembles de fichiers/répertoires. En se rappelant les possibilités de CALL, dans le DO du FOR, on aperçoit la puissance du batch.
Pipes | Redirections > >> et Filtres | sert à détourner la sortie standard d’une commande, vers l’entrée standard d’une autre commande. > sert à détourner la sortie standard d’une commande, vers un (nouveau) fichier, ou vers l’entrée standard d’une autre commande. >> sert à détourner la sortie standard d’une commande, en ajout d’un fichier existant. Les filtres sont des commandes externes (des programmes, en fait), prévu pour recevoir des informations arrivant sur l’entrée standard, les traiter, et envoyer le résultat sur la sortie standard. Les plus connus sont : More, Find, Sort. More sert à attendre, page par page ; Find filtre les lignes qui contiennent une certaine chaîne de caractère ; Sort tri (pour les anglophones, "Sort sort") Quelques exemples : dir *.* | more va visualiser les fichiers du répertoire courant, page par page dir *.exe > tmp.txt le résultat sera enregistré dans le (nouveau) fichier ’tmp.txt’. dir *.bat >> tmp.txt le résultat sera ajouté en fin du fichier ’tmp.txt’. Un exemple plus mieux bien (en terme de complétude) (b11.bat) : @echo off set REP=C:Dev echo Voici la liste des répertoires de %REP% > %TEMP%\mp.txt dir %REP% /B /S /A:D >> %TEMP%\mp.txt echo - >> %TEMP%\mp.txt echo Et voici l’arborescence de %REP% >> %TEMP%\mp.txt echo . >> %TEMP%\mp.txt echo %REP% >> %TEMP%\mp.txt tree | find "-" >> %TEMP%\mp.txt cls type %TEMP%\mp.txt pause echo - echo Et maintenant un petit tri... echo - echo le fichier ABC.txt non trié : type ABC.txt echo - echo le fichier ABC.txt trié par ordre décroissant type ABC.txt | sort /R echo - echo C’est coule, n’est-il pas ?
Aparté opportuniste : Je rappelle que FOR /F permet de parcourir l’intérieur d’un fichier. Quoi, je ne l’avais pas dit ? Et bien, maintenant, c’est fait ! (ceux qui suivent sont donc privilégiés. Normal.) Ces techniques ne se limitent pas aux données : (b12.bat) : @echo off
if exist %0 ( set FICHIER=%0 ) else ( set FICHIER=%0.bat ) set /P MSG= Tapez un message court : type %FICHIER% | find " " | find /V "Pas moi..." > %TEMP%\mp.hta %TEMP%\mp.hta %MSG% del %TEMP%\mp.hta goto :EOF <HTML> <HTA:APPLICATION ID="oHTA" ID="b12HTA" SCROLL="No" SINGLEINSTANCE="yes" CAPTION="yes" BORDER="thin" BORDERSTYLE="complex" CAPTION="yes" CONTEXTMENU="yes" INNERBORDER="no" MAXIMIZEBUTTON="no" MINIMIZEBUTTON="no" NAVIGABLE="no" SCROLL="no" SCROLLFLAT="no" SELECTION="no" SHOWINTASKBAR="yes" SINGLEINSTANCE="yes" SYSMENU="yes" WINDOWSTATE="normal"> <head><TITLE>l’Ecran Noir, version ’Luxe’</TITLE></head> <BODY bgColor=#ffffcc onload="ENinit();"> <DIV ID="TOTO" align=center><STRONG><EM><BR><FONT color=#ff0000 size=4>Salut, lecteur de l’</FONT><FONT color=#000000 size=4> Ecran Noir ! </FONT><BR><BR> <BR><FONT color=#000080>Cette page est un exemple d’utilisation<BR>d’un HTA</FONT> par un Batch.<BR><BR><BR> <FONT color=#8888cc>Et, voici le message tapé : </FONT><BR><FONT color=#880000><DIV ID=PARAM>XXX<BR></DIV></FONT></DIV> <SCRIPT language=JavaScript> function ENinit(){self.resizeTo(340,255); var ligarg=oHTA.commandLine; var i=ligarg.slice(1,255).indexOf("""); var pointeur=document.getElementById(’PARAM’); pointeur.innerText=ligarg.slice(i+3,255) + " ";} </SCRIPT></BODY></HTML> Pas mal, hein ? (aux passage, respectez bien les espacements...
Petit comparatif. Afficher le répertoire courant, en VBscript, Jscript, et Batch : [VBScript] Dim WshShell Set WshShell = WScript.CreateObject("WScript.Shell") WScript.Echo WshShell.CurrentDirectory [JScript] var WshShell = WScript.CreateObject ("WScript.Shell"); WScript.Echo (WshShell.CurrentDirectory); ::Batch echo %CD% Pour paraphraser l’autre, yapafoto !
Outils externes Il est possible d’utiliser, comme commande externe, dans un batch, n’importe quel programme qui fonctionne en ligne de commande. J’en ai réalisé quelques-uns. Suivez le lien "Utilitaires" dans la cadre de gauche (menu).
Un exemple un peu plus gros. Purement Batch, cet exemple est une (toute) petit facturation. Certes, elle est très simplifiée (et, même, simpliste). Néanmoins, elle : - fait des recherches dans un fichier - et même des recherches sur un code partiel (comme article, tapez : "P" [Entrée] - enregistre la sortie dans un fichier - enregistre les factures dans un journal - effectue des justifications à droite (et àgauche) ; voir les montants. - gère un nombre de lignes variables - effectue une requête (liste des factures D’UN client) Bien que sortant du cadre habituel de l’utilisation des Batchs, cet exemple montre que l’utilisation des Batchs peut aller très loin. Il suffit d’un peu d’astuce... Pour lancer l’exemple, tapez simplement : fac [Entrée]
Quelques sites, pour aller moins loin JCB (son site va moins loin pour les Batchs, mais beaucoup plus loin dans de nombreux autres domaines) Jean MST (Le scripting belge, MS, et WSH, pur et dur ; site fortement recommandé) SysInternals (des outils intéressants ; Sysinternals a été racheté par Microsoft) Washington Charles Washington propose des articles, des outils et des liens bien intéressants. Quelques-uns de mes autres sites. Un conseil, relisez d’abord Akim, car il faut savoir naviguer dans cette jungle, pour y trouver des mines intéressantes. Mais il y a ! Python.org Des langages, j’en ai vu pas mal. Python, c’est celui qui me semble être à la fois le plus puissant/complet, et un des plus simples. Il peut se combiner très facilement avec les Batchs (dans tous les sens).
Pour aller plus loin ; quelques pistes à suivre : - HELP [Entrée]
- dir %windir%\system32*.exe /B /P
- Mme Irma, voyante Batch attitrée
- Virus & Pirate magazines se voulant rebelles, mais finalement assez consensuels (à lire avec un certain recul) ; sont devenus quasi introuvables.
- Internet (à consulter avec un esprit critique extrêmement poussé)
|