For en batch a un comportement étrange lors de la lecture de dossiers

J'essaie de faire un lot simple (ce n'est pas tout, mais c'est la partie qui fait que tout échoue)

@echo off for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do ( echo %%G set fullpath=%%G set basename=%fullpath:~7% echo %fullpath% echo %basename% ) 

Ce script est supposé fonctionner à partir de tous les jours, d'où le drôle de boucle. Il est censé regarder à travers le directory et ensuite faire des trucs.

Dans ce directory particulier, il existe 3 autres directorys: bomslenovodb , cpat et finance

La sortie attendue

 e:\tmp\bomslenovodb e:\tmp\bomslenovodb bomslenovodb e:\tmp\cpat e:\tmp\cpat cpat e:\tmp\finance e:\tmp\finance finance 

La sortie réelle

 First run e:\tmp\bomslenovodb ECHO is off. ECHO is off. e:\tmp\bomslenovodb e:\tmp\cpat ECHO is off. ECHO is off. e:\tmp\cpat e:\tmp\finance Second run ECHO is off. ECHO is off. e:\tmp\finance e:\tmp\bomslenovodb e:\tmp\finance ECHO is off. e:\tmp\bomslenovodb e:\tmp\cpat e:\tmp\finance Third run ECHO is off. e:\tmp\cpat e:\tmp\finance e:\tmp\finance ECHO is off. e:\tmp\finance e:\tmp\bomslenovodb e:\tmp\finance e:\tmp\finance Fourth run e:\tmp\bomslenovodb e:\tmp\cpat e:\tmp\finance e:\tmp\finance e:\tmp\cpat e:\tmp\finance e:\tmp\finance e:\tmp\finance e:\tmp\finance 

Il me semble que le set fullpath=%%G ne se comporte pas comme prévu, donc la valeur n'est pas correctement définie.

Im sur une machine Windows Server 2008, des idées?

Erreur de lot classique 🙂

La command SET fonctionne bien. C'est votre expansion qui échoue.

%VAR% extension %VAR% se produit lorsque l'instruction est analysée et toutes les commands dans la boucle FOR sont analysées à la fois. Il en va de même pour tout bloc de code entre parenthèses. Ainsi, les valeurs de %fullpath% et %basename% sont constantes tout au long de l'exécution de la boucle FOR – les valeurs qui existaient avant la saisie de la boucle (indéfinie dans ce cas).

Le correctif consiste à utiliser une extension retardée, qui se produit juste avant l'exécution de la command. L'expansion retardée doit être activée avec setlocal enableDelayedExpansion avant de pouvoir l'utiliser. Et la syntaxe pour l'expansion change à !VAR! .

 @echo off setlocal enableDelayedExpansion for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do ( echo %%G set fullpath=%%G set basename=!fullpath:~7! echo !fullpath! echo !basename! ) 

Mais il y a encore un problème potentiel. Les noms de files peuvent contenir le ! caractère et toutes les variables FOR contenant ! sera corrompu lors de l'expansion lorsque l'extension retardée est activée. La solution consiste à activer ou à désactiver l'expansion retardée dans la boucle.

 @echo off for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do ( echo %%G set fullpath=%%G setlocal enableDelayedExpansion set basename=!fullpath:~7! echo !fullpath! echo !basename! endlocal ) 

Si vous devez protéger ! littéraux, et vous avez besoin de vos affectations variables pour persister à travers les itérations, alors la chose la plus simple à faire est d'utiliser une procédure CALLed afin que vous puissiez utiliser une expansion normale. Il suffit de transférer la valeur de variable FOR à un paramètre CALL. Mais utiliser CALL est significativement plus lent que tout mettre directement dans la boucle.

 @echo off for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do call :proc "%%G" exit /b :proc echo %~1 set "fullpath=%~1" set "basename=%fullpath:~7%" echo %fullpath% echo %basename% exit /b