IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Scripts/Batch Discussion :

For et if exist


Sujet :

Scripts/Batch

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 165
    Points : 90
    Points
    90
    Par défaut For et if exist
    Bonjour,

    je rencontre un problème agaçant avec une boucle for incluant des sous instructions, voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    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
    le but :

    1.lecture du fichier Contenu.txt dont voici un échantillon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    %SystemDrive%\def.txt
    %SystemDrive%\x.exe
    %SystemDrive%\abc.txt
    2. Vérification de la présence du fichier sur le disque dur, lu sur la ligne l de Contenu.txt :
    - si ce fichier est présent, sortir définitivement de la boucle et appliquer les instructions d'après, il ne faut pas que les lignes suivantes soient lues
    - si ce fichier n'est pas présent, passer à la ligne l+1, et ainsi de suite jusqu'à la fin de la lecture ; si toujours rien trouvé, passer à :fin

    J'ai également essayer d'assigner %%a à une variable :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Rem Si le fichier décrit à la ligne lue est présent sur le disque dur :
    if exist "%%a" (
    set %filename%=%%a
    mais à ce niveau, echo %filename% ne renvoie rien, donc le fichier journal.txt est vide.
    Il semblerait qu'en plus du problème initial, les variables d'environnement soient mal tolérées et que C:\ marche mieux que %systemdrive%

    Quelle serait votre approche dans ce genre de circonstance ?

    Merci

  2. #2
    Membre émérite Avatar de Drizzt [Drone38]
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2004
    Messages
    1 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 001
    Points : 2 453
    Points
    2 453
    Par défaut
    Je n'ai pas bien compris quel était ton problème.

    Quel est l'interêt du compteur si tu veux sortir des que tu trouves un fichier ?


    Ca sans les % autour de filename ça fonctionnera mieux.

    Pour sortir de ton for, un goto fera l'affaire.
    Je ne réponds pas aux questions techniques par MP, le forum est là pour cela.

    La crypto c'est comme les flambys, une fois que tu as trouvé la languette tu as juste à tirer pour tout faire tomber.

    (\ _ /)
    (='.'=)
    Voici Lapinou. Aidez le à conquérir le monde
    (")-(") en le reproduisant

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 165
    Points : 90
    Points
    90
    Par défaut
    Salut,

    Quel est l'interêt du compteur si tu veux sortir des que tu trouves un fichier ?
    le compteur me servira par la suite qui est indépendante de cette portion du batch, ce qui compte c'est qu'il passe de 0 à 1 dans le cas où un fichier de Contenu.txt soit présent sur le disque dur

    autant pour moi c'est une erreur de copier-coller sur le forum, mais ça ne résoud pas le problème

    le souci avec ça, c'est que %filename% n'est pas mémorisé à la sortie de la boucle, et c'est bien ça le problème, ce que je souhaite c'est que le fichier journal.txt soit rempli avec le nom du fichier trouvé sur le dd lors du test dans la boucle for

  4. #4
    Membre émérite Avatar de Drizzt [Drone38]
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2004
    Messages
    1 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 001
    Points : 2 453
    Points
    2 453
    Par défaut
    Ah ben oui mais tu n'avais pas dis ce qui ne fonctionnait pas.

    Bref

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @echo off
    setlocal enableDelayedExpansion
    
    set Compteur=0
    
    for /f "delims=" %%a in (Contenu.txt) do (
        if exist "%%a" (
            type blabla.txt >> fichier_tiers.txt
            echo %%a present > journal.txt
            set /a Compteur=1
            goto :fin
        )
    )
    
    :fin
    Ceci fonctionne très bien (avec tokens=* aussi d'ailleurs).

    Pour ton compteur, pas la peine de faire un +1 vu qu'il est à 0 avant et que tu ne l'incremente qu'une fois. Si par hasard tu voulais l'incrementer plusieurs fois, ta syntaxe est fausse en plus, il faudrait mettre des ! au lieu de % (en activant les expansions retardées de variables comme je l'ai fait).

    J'ai aussi mis > au lieu de >> pour journal.txt afin d'écraser l'existant.

    Bref je ne vois pas de problème majeur dans ton code, si ça ne marche pas explicite plus clairement ce qu'il te renvoie, dis nous si il rentre dans la boucle ...


    Pour le %SystemDrive%, je n'ai pas testé mais je suppute que les % posent problème.
    Je ne réponds pas aux questions techniques par MP, le forum est là pour cela.

    La crypto c'est comme les flambys, une fois que tu as trouvé la languette tu as juste à tirer pour tout faire tomber.

    (\ _ /)
    (='.'=)
    Voici Lapinou. Aidez le à conquérir le monde
    (")-(") en le reproduisant

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 165
    Points : 90
    Points
    90
    Par défaut
    Salut,

    merci pour cette réponse qui semble résoudre en partie le pb. En effet, les % de %systemdrive%, %systemroot% semblent gêner.

    Si je mets par exemple dans Contenu.txt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    %systemroot%\abc.txt
    C:\windows\abc.txt
    le test s'arrête sur C:\windows\abc.txt et non pas sur le premier comme attendu. Est-ce que tu as une idée de comment "forcer" la reconnaissance de ces variables d'environnement ?

  6. #6
    Membre émérite Avatar de Drizzt [Drone38]
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2004
    Messages
    1 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 001
    Points : 2 453
    Points
    2 453
    Par défaut
    Bon alors c'est tiré par les cheveux mais ça marche.
    Il doit y avoir plus simple...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @echo off
    setlocal enableDelayedExpansion
    
    for /f "delims=" %%a in (Contenu.txt) do (
    	
         echo %%a | findstr .*  > tmp.work
         set /p filename=<tmp.work
         if exist !filename! (
             echo %%a | findstr .* > journal.txt
             goto :fin
        )
    )
    
    :fin
    del tmp.work
    On utilise le fait que findstr interprete les variables d'environnement lors de son retour.
    Je te laisse adapter à tes besoins.
    Je ne réponds pas aux questions techniques par MP, le forum est là pour cela.

    La crypto c'est comme les flambys, une fois que tu as trouvé la languette tu as juste à tirer pour tout faire tomber.

    (\ _ /)
    (='.'=)
    Voici Lapinou. Aidez le à conquérir le monde
    (")-(") en le reproduisant

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 165
    Points : 90
    Points
    90
    Par défaut
    Je viens de tester cette solution ingénieuse, ça a l'air de marcher

    Mais le gros problème - j'en suis désolé - c'est qu'au niveau rapidité on perd beaucoup. Il y a plus de 10000 lignes à tester et le temps d'exécution de ce bloc est beaucoup plus long qu'avec les méthodes précédentes.

    Avant, en lieu et place de cette boucle for incluant un "if exist", le batch contenait une accumulation gigantesque de lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    if exist "%systemdrive%\abc.txt" (
    blabla
    echo %systemdrive%\abc.txt >> journal.txt
    set compteur=1
    blabla
    )
    etc etc
    ce qui est lourd à gérer et pas forcément subtil, d'où l'idée d'un fichier contenu.txt qui centraliserait touts les fichiers à tester, et le batch s'en trouverait nettement allégé et plus simple à manipuler.

    Est-ce qu'avec call il y aurait moyen de contourner les problèmes rencontrés ? j'avais essayé quelques combinaisons qui n'avaient pas vraiment abouti

    Je te remercie en tout cas pour ton aide assidue et précieuse

  8. #8
    Membre émérite Avatar de Drizzt [Drone38]
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2004
    Messages
    1 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 001
    Points : 2 453
    Points
    2 453
    Par défaut
    Effectivement avec un call ça fonctionne bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @echo off
    setlocal enableDelayedExpansion
    set bTrouve=0
    
    for /f "delims=" %%a in (Contenu.Txt) do (
    	if !bTrouve!==1 goto :exit
    	call :action %%a
    )
    
    :action
    if exist %1 (
        echo %1 est present > journal.txt
        set bTrouve=1
    )
    goto :exit
    
    REM suite du programme
    
    :exit
    Je ne réponds pas aux questions techniques par MP, le forum est là pour cela.

    La crypto c'est comme les flambys, une fois que tu as trouvé la languette tu as juste à tirer pour tout faire tomber.

    (\ _ /)
    (='.'=)
    Voici Lapinou. Aidez le à conquérir le monde
    (")-(") en le reproduisant

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 165
    Points : 90
    Points
    90
    Par défaut
    J'arrange tout ça à ma sauce, mais à priori on dirait que si le fichier factice, présent sur le dd (%systemdrive%\abc.txt), n'est pas sur la première ligne de Contenu.txt, ça ne marche plus ; ex avec :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    %systemroot%\abc.txt
    %systemdrive%\abc.txt

    -> ne marche pas, par contre


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    %systemdrive%\abc.txt
    %systemroot%\abc.txt
    -> marche

    Je vais multiplier les tests encore quelques temps et te tiens au courant de la suite.

  10. #10
    Membre émérite Avatar de Drizzt [Drone38]
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2004
    Messages
    1 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 001
    Points : 2 453
    Points
    2 453
    Par défaut
    Ok, de mon coté avec le code tel quel cela fonctionne que le fichier soit en première, seconde ou dernière ligne.
    Je ne réponds pas aux questions techniques par MP, le forum est là pour cela.

    La crypto c'est comme les flambys, une fois que tu as trouvé la languette tu as juste à tirer pour tout faire tomber.

    (\ _ /)
    (='.'=)
    Voici Lapinou. Aidez le à conquérir le monde
    (")-(") en le reproduisant

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 165
    Points : 90
    Points
    90
    Par défaut
    Salut,

    comme je te disais c'est un peu arrangé en fonction du besoin, et les pbs rencontrés sont les suivants :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for /f "delims=" %%a in (Contenu.txt) do (
    if !bTrouve!==1 goto :exit
    if not !bTrouve!==1 call :action "%%a"
    )
    1. j'ai du rajouter des guillemets à %%a vu les espaces dans certains chemins de Contenu.txt (%ProgramFiles%, %userprofile%...). Rien de bien méchant

    2. la ligne "if not..." parait superflue, d'ailleurs elle l'est surement mais le souci c'est que dans tous les cas et si la fin se termine comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    :exit
    if exist journal.txt notepad journal.txt
    le rapport journal.txt s'ouvre autant de fois que s'effectue les tests de la boucle for, et même une fois de plus (si le fichier factice abc.txt est en deuxième ligne de Contenu.txt, le rapport journal.txt s'ouvre 3 fois), il faut le fermer à chaque fois. J'essaye donc de trouver une solution pour qu'il sorte définitivement de la boucle dès lors qu'un fichier de Contenu.txt se trouve sur le dd

    Voici le code entier

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    :abcTest
    set bTrouve=0
    set Chemin=%cd%
    setlocal enableDelayedExpansion
    cd "%Chemin%\Test"
    
    for /f "delims=" %%a in (Contenu.txt) do (
    if !bTrouve!==1 goto :exit
    if not !bTrouve!==1 call :action "%%a"
    )
    
    
    :action
    if exist %1 (
    type "%Chemin%\Topo\blabla.txt" >> %SystemDrive%\fichier_tiers.txt
    echo abc:le %date% à %time% %1 >> "%Chemin%\Topo\journal.txt"
    set bTrouve=1
    echo. >> %SystemDrive%\fichier_tiers.txt
    echo. >> %SystemDrive%\fichier_tiers.txt
    
    :exit
    if exist %SystemDrive%\journal.txt notepad  %SystemDrive%\journal.txt
    Voilà un exemple avec un fichier factice 1.txt sur mon bureau et dans la deuxième ligne de Contenu.txt

    Chemin\Test>if exist "C:\Documents and Settings\user\bureau\1.txt" (
    type "Chemin%\Topo\blabla.txt" 1>>C:\journal.txt
    echo abc:le 15/03/2008 Ó 9:16:25,18 "C:\Documents and Settings\user\bureau\1.txt" >>"Chemin\Topo\journal.txt"
    set bTrouve=1
    echo. 1>>C:\journal.txt
    echo. 1>>C:\journal.txt
    )

    Chemin\Test>if exist C:\fichier_tiers.txt notepad C:\fichier_tiers.txt

    Chemin\Test>(
    if !bTrouve! == 1 goto :exit
    if not !bTrouve! == 1 call :action "%ProgramFiles%\3332"
    )

    Chemin\Test>if exist C:\fichier_tiers.txt notepad C:\fichier_tiers.txt
    On voit bien que journal.txt s'ouvre deux fois, notamment encore une fois après avoir trouvé 1.txt sur le bureau. J'ai pas mis l'echo de ce qui se passe avec la première ligne de Contenu.txt mais il fait la même chose (ouverture de journal.txt alors que le fichier n'existe pas). En revanche au niveau du résultat dans journal.txt c'est bon il ne met que celui qui existe.
    Il y a un pb avec la condition de sortie de la boucle for

    j'ai essayé avec un deuxième call, rien à faire.

  12. #12
    Membre éprouvé
    Avatar de maxim_um
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    895
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 895
    Points : 1 018
    Points
    1 018
    Par défaut
    Avec tous les efforts que tu as entrepris, tu mérites bien un coup de pouce.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    :abcTest
    setlocal enabledelayedexpansion
    set bTrouve=0
    set Chemin=%cd%
    cd "%Chemin%\Test"
    
    for /f " tokens=*" %%i in (Contenu.txt) do call :action "%%i"& if "!bTrouve!"=="1" goto :eof
    goto fin
    
    :action
    if not exist "%~1" goto :eof
    set bTrouve=1
    
    
    type "%Chemin%\Topo\blabla.txt" >> %SystemDrive%\fichier_tiers.txt
    echo abc:le %date% … %time% %1 >> "%Chemin%\Topo\journal.txt"
    echo. >> %SystemDrive%\fichier_tiers.txt
    echo. >> %SystemDrive%\fichier_tiers.txt
    if exist %SystemDrive%\journal.txt notepad %SystemDrive%\journal.txt
    
    
    :fin
    Je ne l'aie pas testé, mais le principe de fonctionnement que tu demandes y est.
    Tu devras néanmoins contrôler de plus près les zones en gras.

    Le script en soi peut encore être amélioré, mais bon, ça te fait déjà une base de travail et ça te permettra d'aller de l'avant.

    Bon courage.

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 165
    Points : 90
    Points
    90
    Par défaut
    Salut maxi mum

    et merci, ça a l'air de fonctionner après de multiples essais qui vont de toute manière se prolonger.

    Je crois que ce qui fait la différence, entre autres, c'est le goto eof, dans mon esprit cette instruction devait faire quitter le programme (fin de fichier), alors que j'ai plutot l'impression que ça fait sortir de la boucle.

    Une petite question à propos du setlocal enabledelayedexpansion : le test que je vous ai montré est reproduit une vingtaine de fois, ce qui change dans les autres tests c'est le fichier Contenu.txt et le chemin du fichier Blabla.txt
    Est-ce que cette instruction peut être mise avant la vingtaine de tests, dans l'en-tête du batch ou vaut-il mieux la laisser dans l'en-tête de chaque test, bref y a-t-il une position plus importante qu'une autre ? Par ailleurs quelle pourrait être son incidence sur la totalité du batch ?

    Je vous remercie bien sincèrement en tout cas

  14. #14
    Membre éprouvé
    Avatar de maxim_um
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    895
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 895
    Points : 1 018
    Points
    1 018
    Par défaut
    salut,

    [Edit]: Mise à jour par délétion et redirection.

    L'instruction «setlocal enabledelayedexpansion» est expliquée plus en détail dans une autre discussion qui lui est exclusivement dédiée: http://www.developpez.net/forums/d69...sion-retardee/

    Le poste correspondant est plus abordable et plus facile à appréhender que ce que j'avais écrit ici.

    [fin Edit]

    Prend garde au sens de l'instruction goto :eof, elle permet de sortir de l'instruction en cours et induit un branchement à la suite de l'instruction appelante.

    J’espère avoir répondu à ta question.


    NB:

    Voilà, il te reste ainsi à placer un EndLocal dans ton script, de t'assurer qu'il est bien exécuté après avoir bien intégré la notion goto :eof.
    Une fois que ton script aura atteint un certain degré de fiabilité, tu pourras passer à l'étape, comment se défaire des expansions retardées.

    Les différents intervenants de developpez.net t'apporteront l'aide dont tu as besoin si tu venais à rencontrer des difficultés au cours de l'évolution de ton script.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Attribute "rel" exists, but can not be used for this element
    Par pasc06 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 27/02/2010, 11h36
  2. Réponses: 0
    Dernier message: 03/12/2008, 16h57
  3. Réponses: 2
    Dernier message: 25/08/2008, 16h37
  4. [PPC][C#][Sql CE] erreur "no data exists for the row/column"
    Par Jessika dans le forum Windows Forms
    Réponses: 6
    Dernier message: 12/04/2007, 12h13
  5. [JpGraph] Erreur : Chosen locale file for error messages does not exist
    Par nagrom dans le forum Bibliothèques et frameworks
    Réponses: 4
    Dernier message: 19/07/2006, 15h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo