[Résolu] Sortir d'une boucle For

Une difficulté, une précision posez vos questions

Modérateur : WIN32-[GG]

Répondre
Hello

[Résolu] Sortir d'une boucle For

Message par Hello »

Bonjour,

je souhaite utiliser une boucle for qui va :
- parcourir chaque ligne d'un fichier Contenu.txt, contenant des chemins de fichiers (ex : %SystemDrive%\abc.txt)
- pour chaque ligne lue, vérifier si ce fichier est présent sur le disque dur
- si c'est le cas, appliquer 2-3 manips et sortir de la boucle
- si ce n'est pas le cas, continuer jusqu'à ce que le fichier Contenu.txt soit parcouru entièrement, si aucun fichier de Contenu.txt n'est trouvé sur le dd, alors passer à autre chose (:suite)

Code : Tout sélectionner

for /f "tokens=*" %%a in (Contenu.txt) do (
if exist "%%a" (
instruction1
instruction 2
instruction 3
intruction 4
)
goto suite
)
:suite
bon, le pb c'est que même si le fichier %SystemDrive%\abc.txt est présent, on reste dans la boucle et il continue de tester toutes les lignes.

Qu'est-ce qui est foireux dans ce code svp ? Merci
Avatar du membre
flox
Administrateur du site
Messages : 158
Enregistré le : 18 janv. 2008 22:05

Re: Sortir d'une boucle For

Message par flox »

Bonjour,

pour ma part dans la configuration suivante on sort bien de la boucle par l'etiquette ":suite"

c:\test.bat

Code : Tout sélectionner

@echo off
for /f "tokens=*" %%a in (Contenu.txt) do (
if exist "%%a" (
echo instruction 1
echo instruction 2
echo instruction 3
echo instruction 4
)
goto suite
)
:suite
pause

c:\Contenu.txt

Code : Tout sélectionner

 
c:\abc.txt
 
Résultat avec un fichier présent "c:\abc.txt"

Code : Tout sélectionner

 
C:\>echo off
instruction 1
instruction 2
instruction 3
instruction 4
Appuyez sur une touche pour continuer...
 
Résultat sans un fichier présent "c:\abc.txt"

Code : Tout sélectionner

Appuyez sur une touche pour continuer...
On sort bien dans tout les cas via l'etiquette ":suite", et c'est même un problème dans le sens ou ton batch ne fera jamais plus d'une boucle, car dans tous les cas fichier ou non présent on quittera forcement la boucle.

Pour faire ce que tu décrit il faut juste enlever le goto, dans ce cas une fois que la boucle aura fini de parcourir le fichier contenu.txt il passera tout seul à la :suite.

Voila un exemple de configuration qui je pense répond à ta problématique.

c:\test.bat

Code : Tout sélectionner

@echo on
for /f "tokens=*" %%a in (Contenu.txt) do (
if exist "%%a" (
echo instruction 1
echo instruction 2
echo instruction 3
echo instruction 4
)
)
pause
c:\Contenu.txt

Code : Tout sélectionner

c:\abcd.txt
c:\abc.txt
Exécution avec le fichier c:\abc.txt présent l'affichage du code est activée "@echo on"

Code : Tout sélectionner

 
C:\>for /F "tokens=*" %%a in (Contenu.txt) do (if exist "%%a" (
echo instruction 1
 echo instruction 2
 echo instruction 3
 echo instruction 4
) )
 
C:\>(if exist "c:\abcd.txt" (
echo instruction 1
 echo instruction 2
 echo instruction 3
 echo instruction 4
) )
 
C:\>(if exist "c:\abc.txt" (
echo instruction 1
 echo instruction 2
 echo instruction 3
 echo instruction 4
) )
instruction 1
instruction 2
instruction 3
instruction 4
 
C:\>pause
Appuyez sur une touche pour continuer...

Exécution sans le fichier c:\abc.txt présent l'affichage du code est activée "@echo on"

Code : Tout sélectionner

C:\>for /F "tokens=*" %%a in (Contenu.txt) do (if exist "%%a" (
echo instruction 1
 echo instruction 2
 echo instruction 3
 echo instruction 4
) )
 
C:\>(if exist "c:\abcd.txt" (
echo instruction 1
 echo instruction 2
 echo instruction 3
 echo instruction 4
) )
 
C:\>(if exist "c:\abc.txt" (
echo instruction 1
 echo instruction 2
 echo instruction 3
 echo instruction 4
) )
 
C:\>pause
Appuyez sur une touche pour continuer...

Voila si ça ne fonctionne pas chez toi poste nous le contenu des instructions de ton "if".

Bon courage
Hello

Re: Sortir d'une boucle For

Message par Hello »

Merci

Le souci c'est que je ne veux pas qu'il teste toutes les lignes du fichier, mais qu'il arrête le test dès lors qu'un fichier est présent sur le dd -> donc en sortant de la boucle. D'autre part, un compteur est initialisé avant cette boucle, il est censé s'incrémenter à partir du moment où un fichier de Contenu.txt est présent sur le dd, et il ne le fait pas.
Pour être plus précis, voici l'ensemble de cette section :
Rem initialisation du compteur
set Compteur=0

Rem le dossier "Repertoire" contient le fichier Contenu.txt, et se trouve dans le même répertoire que le batch
cd \Repertoire
Rem pour chaque ligne du fichier Contenu.txt
for /f "tokens=*" %%a in (Contenu.txt) do (
Rem Si le fichier décrit à la ligne lue est présent sur le disque dur :
if exist "%%a" (
Rem Copier un truc indépendant de %%a du fichier blabla.txt vers le fichier fichier_tiers.txt :
type blabla.txt >> fichier_tiers.txt
Rem écrire que le fichier de la ligne lue est présent dans le fichier journal.txt
echo %%a present >> journal.txt
Rem incrémenter de 1 le compteur :
set /a Compteur=%Compteur%+1
Rem sauter deux lignes dans le fichier fichier_tiers.txt :
echo. >> fichier_tiers.txt
echo. >> fichier_tiers.txt
Rem je voudrais qu'il sorte ici s'il a trouvé un fichier -> :fin, sinon continuer la lecture de Contenu.txt
)
)

:fin
En fait, il n'incrémente pas le compteur (echo %Compteur% avant :fin donne 0), et n'écrit pas dans les fichiers journal.txt et fichier_tiers.txt. Il n'y a aucun message d'erreur. J'espère être assez clair dans les explications, merci pour ton aide .
Avatar du membre
flox
Administrateur du site
Messages : 158
Enregistré le : 18 janv. 2008 22:05

Re: Sortir d'une boucle For

Message par flox »

Ok,

effectivement j'ai déjà remarqué quelques petits soucis dans les boucles "For", certaines instructions ne sont pas prises en compte. :(

Mais il y a une solution :)

Elle consiste à sortir les commandes de la boucle for via une étiquette...


Exemple avec un fichier c:\abc.txt noté dans contenu.txt et existant sur le disque dur :

Code : Tout sélectionner

@echo off
Rem initialisation du compteur
set Compteur=0
 
Rem le dossier "Repertoire" contient le fichier Contenu.txt, et se trouve dans le même répertoire que le batch
rem cd \Repertoire
Rem pour chaque ligne du fichier Contenu.txt
for /f "tokens=*" %%a in (Contenu.txt) do (
Rem Si le fichier décrit à la ligne lue est présent sur le disque dur :
if exist "%%a" (
set filename=%%a
goto work
)
)
 
:work
Rem Copier un truc indépendant de %%a du fichier blabla.txt vers le fichier fichier_tiers.txt :
type blabla.txt >> fichier_tiers.txt
Rem écrire que le fichier de la ligne lue est présent dans le fichier journal.txt
echo %filename% present >> journal.txt
Rem incrémenter de 1 le compteur :
set /a Compteur=%Compteur%+1
Rem sauter deux lignes dans le fichier fichier_tiers.txt :
echo. >> fichier_tiers.txt
echo. >> fichier_tiers.txt
Rem je voudrais qu'il sorte ici s'il a trouvé un fichier -> :fin, sinon continuer la lecture de Contenu.txt
Rem -> Si on est ici c'est que le fichier est trouvé ;-)
pause
 

ton fichier journal:

Code : Tout sélectionner

c:\abc.txt present

Ça à l'air de marcher, dis moi si c'est ok.
Hello

Re: Sortir d'une boucle For

Message par Hello »

Salut flox,

non, j'ai l'impression que ça ne marche pas et que %filename% n'est pas mémorisé. Si j'ajoute :
if exist "%%a" (
set filename=%%a
echo %filename%
goto work
)
Il met simplement echo alors qu'à la ligne du dessus il met bien if exist C:\abc.txt. Du coup la variable n'est pas transmise à :work et le fichier journal.txt est vide... Je précise que Contenu.txt contient :

Code : Tout sélectionner

%SystemDrive%\def.txt
%SystemDrive%\x.exe
%SystemDrive%\abc.txt
et que seul %SystemDrive%\def.txt est réellement présent sur le dd. Naturellement j'ai tenté d'autres combinaisons mais aucune n'aboutit au résultat attendu.
Avec call il n'y aurait pas moyen de s'en sortir autrement ?
Avatar du membre
flox
Administrateur du site
Messages : 158
Enregistré le : 18 janv. 2008 22:05

Re: Sortir d'une boucle For

Message par flox »

Re,
Je pense que l'erreur vient du fichier contenu.txt

Code : Tout sélectionner

%SystemDrive%\def.txt
%SystemDrive%\x.exe
%SystemDrive%\abc.txt
Essaye en remplaçant par:

Code : Tout sélectionner

c:\def.txt
c:\x.exe
c:\abc.txt
avec ce code là:

Code : Tout sélectionner

@echo off
Rem initialisation du compteur
set Compteur=0
 
Rem le dossier "Repertoire" contient le fichier Contenu.txt, et se trouve dans le même répertoire que le batch
rem cd \Repertoire
Rem pour chaque ligne du fichier Contenu.txt
for /f "tokens=*" %%a in (Contenu.txt) do (
Rem Si le fichier décrit à la ligne lue est présent sur le disque dur :
if exist "%%a" (
set filename=%%a
goto work
)
)
 
:work
Rem Copier un truc indépendant de %%a du fichier blabla.txt vers le fichier fichier_tiers.txt :
rem type blabla.txt >> fichier_tiers.txt
Rem écrire que le fichier de la ligne lue est présent dans le fichier journal.txt
echo %filename% present >> journal.txt
Rem incrémenter de 1 le compteur :
set /a Compteur=%Compteur%+1
Rem sauter deux lignes dans le fichier fichier_tiers.txt :
echo. >> fichier_tiers.txt
echo. >> fichier_tiers.txt
Rem je voudrais qu'il sorte ici s'il a trouvé un fichier -> :fin, sinon continuer la lecture de Contenu.txt
Rem -> Si on est ici c'est que le fichier est trouvé ;-)
pause
chez moi le fichier c:\journal.txt égale ça avec uniquement le fichier c:\abc.txt présent.

Code : Tout sélectionner

c:\abc.txt present
Hello

Re: Sortir d'une boucle For

Message par Hello »

Il semblerait que tu aies raison. Cette modif entraîne la mémorisation de la variable %filename% dans :work (curieusement elle ne l'est toujours pas dans la boucle initiale ?). En revanche c'est une contrainte lourde que de renoncer à l'utilisation de variables d'environnements, car le batch perd son universalité.

Aïe...
Avatar du membre
flox
Administrateur du site
Messages : 158
Enregistré le : 18 janv. 2008 22:05

Re: Sortir d'une boucle For

Message par flox »

Il est vrais, c'est moyennement propre, mais l'installation d'un windows sur le une partition d: reste rare.
Hello

Re: Sortir d'une boucle For

Message par Hello »

Le pb c'est que ce fichier Contenu.txt n'est qu'un échantillon, les lignes du véritable fichier peuvent se compter par centaines et inclure des fichiers contenus dans le profil utilisateur qui lui se trouve bien plus souvent dans des partoches extérieures à %systemdrive%
Par conséquent il est impératif de trouver une solution tolérant les variables d'environnement

Je vais continuer de chercher, si jamais tu as d'autres idées elles seront tjs les bienvenues

Merci pour ton aide
Avatar du membre
flox
Administrateur du site
Messages : 158
Enregistré le : 18 janv. 2008 22:05

Re: Sortir d'une boucle For

Message par flox »

Bonjour,

Une solution pourrait être de remplacer préalablement toutes les variables d'environnement directement dans ton fichier contenu.txt.

Cela est réalisable via l'exécutable switch.exe.

Exemple de remplacement code à insérer au début de ton .bat

Code : Tout sélectionner

rem remplace tous les caractères % par des @ afin de pouvoir être traité
c:\switch.exe c:\contenu.txt "%%" "@"
rem remplace toutes la variables d'environnement, on peut ajouter celle que l'on souhaite 
c:\switch.exe c:\contenu.txt "@systemdrive@" "%systemdrive%"
c:\switch.exe c:\contenu.txt "@userprofile@" "%userprofile%"
Voila certes une solution peut propre mais fonctionnelle.
Répondre