28 votes

Fichiers batch Windows : définition d'une variable dans une boucle for

J'ai un certain nombre de fichiers avec le même schéma de dénomination. Par exemple, quatre fichiers sont appelés "num_001_001.txt", "num_002_001.txt", "num_002_002.txt", "num_002_003.txt"

La première série de chiffres représente le "paquet" dont il provient, et la deuxième série de chiffres sert simplement à les distinguer les uns des autres. Dans cet exemple, nous avons donc un fichier dans le paquet 001 et trois fichiers dans le paquet 002.

Je suis en train d'écrire une commande batch pour Windows Vista afin de prendre tous les fichiers et de les déplacer dans leurs propres répertoires, où chaque répertoire représente un paquet différent. Je veux donc déplacer tous les fichiers du paquet 001 dans le répertoire "001" et tous ceux du paquet 002 dans le répertoire "002"

J'ai réussi à écrire un script qui va itérer sur tous les fichiers txt et les afficher en écho. J'ai également écrit un script qui déplacera un fichier dans un autre emplacement, et qui créera le répertoire s'il n'existe pas.

Je me suis rendu compte que je devais utiliser des sous-chaînes, et j'ai donc utilisé la syntaxe %var:~start,end% pour les obtenir. En guise de test, j'ai écrit ceci pour vérifier que je peux effectivement extraire la sous-chaîne et créer un répertoire de manière conditionnelle

@echo off
set temp=num\_001\_001.txt
NOT IF exist %temp:~0,7%\\
  mkdir %temp:~0,7%

Et cela fonctionne. C'est très bien.
J'y ai donc ajouté la boucle for.

@echo off
FOR /R %%X IN (\*.txt) DO (
  set temp=%%~nX
  echo directory %temp:~0,7%
)

Mais il s'agit de mon résultat :

directory num\_002
directory num\_002
directory num\_002
directory num\_002

Qu'est-ce qui ne va pas ? Est-ce que Vista ne permet pas de réaffecter les variables à chaque itération ? Les quatre fichiers sont dans mon répertoire, et l'un d'entre eux devrait créer num_001. J'ai mis différents fichiers avec 003 004 005 et tout était le nom du dernier paquet. Je suppose que quelque chose ne va pas dans la façon dont je configure les choses.

J'ai trouvé différentes solutions pour faire le travail, mais je ne comprends pas pourquoi un concept aussi simple ne fonctionne pas.

59voto

configurator Points 15594

Votre problème est que la variable est remplacée lorsque le processeur de traitement par lots lit la commande for, avant qu'elle ne soit exécutée.

Essayez ceci :

SET temp=Hello, world!
CALL yourbatchfile.bat

Et vous verrez Hello imprimé 5 fois.

La solution est l'expansion différée ; vous devez d'abord l'activer, puis utiliser la fonction !temp! au lieu de %temp% :

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /R %%X IN (*.txt) DO (
  set temp=%%~nX
  echo directory !temp:~0,7!
)

Véase ici pour plus de détails.

15voto

bk1e Points 13737

Une autre solution consiste à déplacer le corps du for à une sous-routine et call il.

@echo off
FOR /R %%X IN (*.txt) DO call :body %%X
goto :eof

:body
set temp=%~n1
echo directory %temp:~0,7%
goto :eof

Pourquoi faire cela ? L'une des raisons est que le processeur de commandes de Windows est gourmand en parenthèses, et les résultats peuvent être surprenants. Je rencontre généralement ce problème lors du déréférencement de variables contenant des C:\Program Files (x86) .

Si le processeur de commande de Windows était moins gourmand, le code suivant imprimerait soit One (1) Two (2) ou rien du tout :

@echo off
if "%1" == "yes" (
   echo 1 (One)
   echo 2 (Two)
)

Cependant, ce n'est pas ce qu'il fait. Soit il imprime 1 (One 2 (Two) qui manquent d'un ) ou bien il imprime 2 (Two) . Le processeur de commande interprète le ) après One comme la fin de la if traite le deuxième echo comme s'il était en dehors de la if et ignore la déclaration finale ) .

5voto

bk1e Points 13737

Je ne suis pas sûr que cela soit officiellement documenté, mais vous pouvez simuler une expansion retardée en utilisant la fonction call déclaration :

@echo off
FOR /R %%X IN (*.txt) DO (
  set temp=%%~nX
  call echo directory %%temp:~0,7%%
)

Le fait de doubler les signes de pourcentage reporte la substitution de la variable à la deuxième évaluation. Cependant, l'expansion retardée est beaucoup plus simple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X