locked
cmd: smyčka FOR mi nechce fungovat

    Dotaz

  • D:\Dokumenty\ElektroSystem\skripty>for %ahoj in ("10 20 30 40 50") do echo %ahoj%
    %ahoj nebyl nyní očekáván.

    D:\Dokumenty\ElektroSystem\skripty>for %%ahoj in ("10 20 30 40 50") do echo %ahoj%
    %%ahoj nebyl nyní očekáván.

    Chci, aby to na zkoušku vypisovalo postupně 10 až 50. To druhý by mělo fungovat ve skriptu. FOR /? jsem přečetl a stále nevím, kde dělám chybu.


    Tomáš Vognar
    17. srpna 2011 13:38

Odpovědi

  • ehm ... RTFM  setlocal /?  nebo set /? nebo cmd /?napovi :)


    @echo off
    setlocal ENABLEDELAYEDEXPANSION
    set site=10 20 30 40 50
    set uzly=03 04 05 06 07 08 09 10 11 80
    set string=
    
    for %%s in (%site%) do (
    	for %%u in (%uzly%) do (
    		set string=!string! -L 5%%s%%u:10.252.%%s.%%u:22
    	)
    )
    
    set string=putty -p 2404 %string% ris@iec_nat
    echo %string%
    
    start %string%
    

    Proste pokud pracujes s promennou (samozrejme jinou nez promennou cyklu) v cyklu musis povolit delayed variable expansion jinak hoblujes furt jedinou poprve vyhodnocenou


    MP




    18. srpna 2011 12:57
    Moderátor
  • Pokud to mas v davkovem souboru napis to takto:

    @ECHO OFF
    
    for %%A in (10 20 30 40 50) do echo %%A
    
    Vystupem je:

    10

    20

    30

    40

    50

     

    Chtel jsi to takto?

     

    Jde to i zanorit a udelat celkem velky program:

    FOR /D %%a IN (*.*) DO (
     if exist %%a\Ostatni\ (
     echo Stanice: %%a
     FOR /F %%r IN (roky) DO (
     FOR %%s IN (%%a\Ostatni\C%%r????.DAT) DO (
     echo %%s
     if not exist %%a\Ostatni\C.DAT\  mkdir %%a\Ostatni\C.DAT
     if not exist %%a\Ostatni\C.DAT\20%%r\ mkdir %%a\Ostatni\C.DAT\20%%r
     move /Y %%s %%a\Ostatni\C.DAT\20%%r\
     )
     FOR %%s IN (%%a\Ostatni\D%%r????.DAT %%a\Ostatni\D%%r????.PLA) DO (
     echo %%s
     if not exist %%a\Ostatni\D.DAT\  mkdir %%a\Ostatni\D.DAT
     if not exist %%a\Ostatni\D.DAT\20%%r\ mkdir %%a\Ostatni\D.DAT\20%%r
     move /Y %%s %%a\Ostatni\D.DAT\20%%r\
     )
     FOR %%s IN (%%a\Ostatni\U%%r????.DAT %%a\Ostatni\U%%r????.POL) DO (
     echo %%s
     if not exist %%a\Ostatni\U.DAT\  mkdir %%a\Ostatni\U.DAT
     if not exist %%a\Ostatni\U.DAT\20%%r\ mkdir %%a\Ostatni\U.DAT\20%%r
     move /Y %%s %%a\Ostatni\U.DAT\20%%r\
     )
     FOR %%s IN (%%a\Ostatni\R%%r????.DAT) DO (
     echo %%s
     if not exist %%a\Ostatni\R.DAT\  mkdir %%a\Ostatni\R.DAT
     if not exist %%a\Ostatni\R.DAT\20%%r\ mkdir %%a\Ostatni\R.DAT\20%%r
     move /Y %%s %%a\Ostatni\R.DAT\20%%r\
     )
     FOR %%s IN (%%a\Zaloha\zal%%r*.DAT) DO (
     echo %%s
     if not exist %%a\Zaloha\20%%r\  mkdir %%a\Zaloha\20%%r
     move /Y %%s %%a\Zaloha\20%%r\
     )
     )
     )
    )
    

    Prochazi to adresare a uvnitr nich v podadresari Ostatni bere soubory Crrmmdd.DAT a kopiruje je po rocich do podadresaru Ostatni\C.DAT\rr\*.*

    Podobne to dela i s ostatnimi soubory.

     

    PS: V cyklu se pouziva jenom jednopismenkova promenna. Rozlisuji se velka a mala pismena!


    JCH

    17. srpna 2011 14:21
  • Retezcove operace nefunguji s ridicimi promennymi cyklu. Pouzij pom. promennou

    for %%s in (%site%) do (
    	set POM=%%s
    	echo pocitam !POM:~0,1!+!POM:~1!
    	set /a l=!POM:~0,1!+!POM:~1!
    	echo !l!
    
    )

    MP

    5. března 2015 14:05
    Moderátor

Všechny reakce

  • Pokud to mas v davkovem souboru napis to takto:

    @ECHO OFF
    
    for %%A in (10 20 30 40 50) do echo %%A
    
    Vystupem je:

    10

    20

    30

    40

    50

     

    Chtel jsi to takto?

     

    Jde to i zanorit a udelat celkem velky program:

    FOR /D %%a IN (*.*) DO (
     if exist %%a\Ostatni\ (
     echo Stanice: %%a
     FOR /F %%r IN (roky) DO (
     FOR %%s IN (%%a\Ostatni\C%%r????.DAT) DO (
     echo %%s
     if not exist %%a\Ostatni\C.DAT\  mkdir %%a\Ostatni\C.DAT
     if not exist %%a\Ostatni\C.DAT\20%%r\ mkdir %%a\Ostatni\C.DAT\20%%r
     move /Y %%s %%a\Ostatni\C.DAT\20%%r\
     )
     FOR %%s IN (%%a\Ostatni\D%%r????.DAT %%a\Ostatni\D%%r????.PLA) DO (
     echo %%s
     if not exist %%a\Ostatni\D.DAT\  mkdir %%a\Ostatni\D.DAT
     if not exist %%a\Ostatni\D.DAT\20%%r\ mkdir %%a\Ostatni\D.DAT\20%%r
     move /Y %%s %%a\Ostatni\D.DAT\20%%r\
     )
     FOR %%s IN (%%a\Ostatni\U%%r????.DAT %%a\Ostatni\U%%r????.POL) DO (
     echo %%s
     if not exist %%a\Ostatni\U.DAT\  mkdir %%a\Ostatni\U.DAT
     if not exist %%a\Ostatni\U.DAT\20%%r\ mkdir %%a\Ostatni\U.DAT\20%%r
     move /Y %%s %%a\Ostatni\U.DAT\20%%r\
     )
     FOR %%s IN (%%a\Ostatni\R%%r????.DAT) DO (
     echo %%s
     if not exist %%a\Ostatni\R.DAT\  mkdir %%a\Ostatni\R.DAT
     if not exist %%a\Ostatni\R.DAT\20%%r\ mkdir %%a\Ostatni\R.DAT\20%%r
     move /Y %%s %%a\Ostatni\R.DAT\20%%r\
     )
     FOR %%s IN (%%a\Zaloha\zal%%r*.DAT) DO (
     echo %%s
     if not exist %%a\Zaloha\20%%r\  mkdir %%a\Zaloha\20%%r
     move /Y %%s %%a\Zaloha\20%%r\
     )
     )
     )
    )
    

    Prochazi to adresare a uvnitr nich v podadresari Ostatni bere soubory Crrmmdd.DAT a kopiruje je po rocich do podadresaru Ostatni\C.DAT\rr\*.*

    Podobne to dela i s ostatnimi soubory.

     

    PS: V cyklu se pouziva jenom jednopismenkova promenna. Rozlisuji se velka a mala pismena!


    JCH

    17. srpna 2011 14:21
  • Testuji na W 7 :-). Funguje z prikazove radky. Jednodussi zapis pro dany pripad:

    for /L %C in (10,10,50) do echo %C

     

    17. srpna 2011 14:39
    Moderátor
  • Ejhle, uvozovky přebývaly. Moc děkuji.

     

    Ale byl tam ještě jeden problém, na který jsem právě přišel, pro mě nepochopitelný. Ve skriptu je toto

    set site=10 20 30 40 50
    for %%sit in (%site%) do echo %%sit

    vysledek: %sit nebyl nyní očekáván.

    pokud proměnnou sit nahradím A, jak jste mi to poslal, tak to funguje. Že by mu vadilo, že sit je podmnožinou site?

     

    Ano, zanořovat budu. Tohle je jen test. Normálně dělám skripty v bashi; když mám stvořit něco ve Windows, je to úplně jiná logika.


    Tomáš Vognar
    17. srpna 2011 14:49
  • V cyklu se pouziva jenom jednopismenkova promenna. Rozlisuji se velka a mala pismena!

     

    Mam to v puvodnim prispevku az na konci. 

     

    set site=10 20 30 40 50
    for %%s in (%site%) do echo %%s


    JCH

    17. srpna 2011 14:54
  • pokud proměnnou sit nahradím A, jak jste mi to poslal, tak to funguje. Že by mu vadilo, že sit je podmnožinou site?
    Tomáš Vognar

    S tou promenou je to nějaký divný; když zkouším nahradit zároveň proměnnou za klíčovými slovy 'for' a 'echo'

    %%A, %%B, %%b     funguje

    %%sit, %%BLBEC, %%Un, %%wowo, %%BR   nefunguje (%Br nebyl nyní očekáván)

     

    Ten cmd je nějaký náladový nebo snese jen jednopísmenné proměnné


    Tomáš Vognar
    17. srpna 2011 14:59
  • ANO  jen jednopísmenkové!
    JCH
    17. srpna 2011 15:00
  • Děkuji, zatímco jsem zkoušel, vy jste odpověděl. Fajn, hlavně že jsem o kus dále.
    Tomáš Vognar
    17. srpna 2011 15:02
  • v cyklu for je mozne pouzit max 26 jednoznoznakovych promennych (zejmena v parsovanio tokens z textoveho vstupu) ktere jdou abecedne po sobe pokud je prvni %a pak je druha %b atd. az po max %z

     

    MP


    17. srpna 2011 19:41
    Moderátor
  • Není tomu tak. Minimálně od WinXP jde použít 26 (velká písmena) + 26 (malá písmena). Moje chytrá kniha říká, že příkaz FOR rozlišuje velká a malá písmena a doslova uvádí že %%A je v tomto kontextu jiná proměnná než %%a.

     

    Toto funguje bez problému na WinXP:

    @ECHO OFF
    for /D %%a IN (*.*) DO (
     echo %%a
     for /D %%A IN (%%a/*.*) DO (
     echo %%a/%%A
     )
    )
    pause
    
    


    PS: To co uvádí Mirek je výstup z parsování ne proměnná cyklu FOR. I to jde ale obejít posunutím (offsetem) dalších parametrů.

    PPS: Ten můj příklad má mouchy (například nepočítá s dlouhými názvy adresářů, které obsahují mezery). Šlo by to opravit, ale nechce se mi s tím nyní hrát. Jako příklad že jde najednou použít %%a i %%A to stačí.


    JCH
    18. srpna 2011 5:20
  • mas pravdu, je to 2x26 (case sensitive) - my co jsme vyrustali v dobe 5bitoveho dalnopisoveho kodu mame nejak averzi k velkym pismenum :)

     

    Kam by se ale vystup z parsovani ukladal jinam nez do promenne?

     

    MP

     



    18. srpna 2011 7:01
    Moderátor
  • Ano ukládá se samozřejmě do proměnné, ale není to řídící proměnná v cyklu FOR o který tazateli původně šlo.

    To parsování opravdu používá jen 26 znaků ale jde to posunout, takže v prvním kolečku jde přečíst prvních 26 hodnot, v dalším dalších 26 hodnot a tak dál.

     

    Myslím ale, že jsme se dostali daleko od původního dotazu.   :-)

     


    JCH
    18. srpna 2011 8:48
  • S konečným skriptem mám stále problém, v cyklech for se netvoří, co potřebuji

     

    @echo off
    
    set site=10 20 30 40 50
    set uzly=03 04 05 06 07 08 09 10 11 80
    set string=
    
    for %%s in (%site%) do (
    	for %%u in (%uzly%) do (
    		set string=%string% -L 5%%s%%u:10.252.%%s.%%u:22
    	)
    )
    
    set string=putty -p 2404 %string% ris@iec_nat
    echo %string%
    
    ::start %string%

     

    Skript mi vypíše toto

    putty -p 2404 -L 55080:10.252.50.80:22 ris@iec_nat

     

    Smyslem skriptu je vytvořit hrozně dlouhý řádkový příkaz a ten potom spustit. Podřetězec "-L 55080:10.252.50.80:22" by se tam měl 50x opakovat v obměněné formě. Když nevypnu na začátku echo, tak vidím, že na 7. řádku dochází k substituci %string% za prázdný řetězec, a to nejspíš ještě před samotným spuštěním skriptu. Místo toho by se měly substituovat výsledky předchozích běhů cyklu for. Zkoušel jsem na 7. řádku místo %string% zapsat %%string nebo !string! (to jsem vyčetl), ale nefunguje to. V podstatě vůbec netuším, jaký je smysl tolika různých zápisů proměnných (%var, %%var, %var%, !var!)

     

     


    Tomáš Vognar
    18. srpna 2011 12:43
  • ehm ... RTFM  setlocal /?  nebo set /? nebo cmd /?napovi :)


    @echo off
    setlocal ENABLEDELAYEDEXPANSION
    set site=10 20 30 40 50
    set uzly=03 04 05 06 07 08 09 10 11 80
    set string=
    
    for %%s in (%site%) do (
    	for %%u in (%uzly%) do (
    		set string=!string! -L 5%%s%%u:10.252.%%s.%%u:22
    	)
    )
    
    set string=putty -p 2404 %string% ris@iec_nat
    echo %string%
    
    start %string%
    

    Proste pokud pracujes s promennou (samozrejme jinou nez promennou cyklu) v cyklu musis povolit delayed variable expansion jinak hoblujes furt jedinou poprve vyhodnocenou


    MP




    18. srpna 2011 12:57
    Moderátor
  • Souhlas  

     

    :-)


    JCH
    18. srpna 2011 13:06
  • Mockrát děkuji.

    Přiznám se že nějaký skript ve Windows píšu velmi zřídka a to se často bez pomoci neobejdu. Ale ukládám si je a snad příště už zas budu o kus chytřejší.


    Tomáš Vognar
    18. srpna 2011 13:17
  • Dovolím si ještě jednu otázečku. V tom cyklu, kde je vždy dvakrát použita řetězcová proměnná %u obsahující dvojciferné číslo, se vyskytla potřeba vždy v druhém případě odstranit začínající nulu. Zkoušel jsem to převést na číslo "set /a v=%u%", ale bylo to považováno za osmičkovou soustavu. Pak jsem zkoušel řetězcové operace "set v=%u:0=%", jenže to mi zruší nuly i na konci. Nevím tedy jak. Druhou možností by bylo mít čísla užložené bez počínajících nul a v těch prvních případech nulu doplňovat na celkové 2 cifry. To ale také nevím jak.

    Poradíte, prosím?

     

    Děkuji


    Tomáš Vognar
    22. srpna 2011 17:11
  • Byl jsi s těmi řetezcovými operacemi hodně blízko.

    set UU=%%u
    if "!UU:~0,1!"=="0" set UU=!UU:~1,1!

    Takže výsledný script by mohl být třeba takovýto:
    .
    @echo off
    setlocal ENABLEDELAYEDEXPANSION
    set site=10 20 30 40 50
    set uzly=03 04 05 06 07 08 09 10 11 80
    set string=
    
    for %%s in (%site%) do (
     for %%u in (%uzly%) do (
     set UU=%%u
     if "!UU:~0,1!"=="0" set UU=!UU:~1,1! 
     set string=!string! -L 5%%s%%u:10.252.%%s.!UU!:22
     )
    )
    
    set string=putty -p 2404 %string% ris@iec_nat
    echo %string%
    
    start %string%
    
    
    


    JCH
    22. srpna 2011 19:17
  • Mockrát děkuji, já jsem očekával, že někdo zareaguje až ráno, tak jsem ještě chvilku přemýšlel a vymyslel jsem něco bez větvení. Kupovivu to funguje, teda jen na ty 2-ciferný - stejně jako Vám. Dost možná nic chytřejšího vymyslet nelze.

    for %%s in (%site%) do (
        for %%u in (%uzly%) do (
            set /a v=1%%u-100
            set string=!string! -L 5%%s%%u:10.252.%%s.!v!:22
        )
    )

    Ale stejně si pořád dělám jasno v označení těch proměnných, je to na mě nějaký složitý. Když to shrnu:

    %abcd%   expanze preprocesorem ještě před samotným spuštěním kódu
    !abcd!     expance za běhu kódu pokud mám nastaveno "setlocal ENABLEDELAYEDEXPANSION"
    %a       expanze za běhu, platí pouze pro řídící proměnnou cyklu for puštěného z ruky
    %%a     expanze za běhu, platí pouze pro řídící proměnnou cyklu for ve skriptu

    Je to tak a kompletní, nebo je to ještě složitější?


    Tomáš Vognar
    22. srpna 2011 20:05
  • Je to ještě složitějši.

    %a nebo %%a je možné použít ne jen jako promměnná cyklu for, ale i jako výstup z parsování token. Viz prispevek Mirka z 17. srpna 2011 19:41

    Výsledkem mohou být naplněné všechny proměnné %a až %z.

     

    To chce nějakou chytrou knihu. Mě pomohlo toto: http://knihy.cpress.cz/prikazovy-radek-microsoft-windows.html


    JCH


    22. srpna 2011 20:28
  • Nedavno jsem neco na toto tema prelozil, snad Vam to pomuze:
     
     
    L.
     On 22.8.2011 22:05, Tomáš Vognar wrote:
    > Mockrát děkuji, já jsem očekával, že někdo zareaguje až ráno, tak jsem
    > ještě chvilku přemýšlel a vymyslel jsem něco bez větvení. Kupovivu to
    > funguje, teda jen na ty 2-ciferný - stejně jako Vám. Dost možná nic
    > chytřejšího vymyslet nelze.
    >
    > for %%s in (%site%) do (
    > for %%u in (%uzly%) do (
    > set /a v=1%%u-100
    > set string=!string! -L 5%%s%%u:10.252.%%s.!v!:22
    > )
    > )
    >
    > Ale stejně si pořád dělám jasno v označení těch proměnných, je to na mě
    > nějaký složitý. Když to shrnu:
    >
    > %abcd% expanze preprocesorem ještě před samotným spuštěním kódu
    > !abcd! expance za běhu kódu pokud mám nastaveno "setlocal
    > ENABLEDELAYEDEXPANSION"
    > %a expanze za běhu, platí pouze pro řídící proměnnou cyklu for puštěného
    > z ruky
    > %%a expanze za běhu, platí pouze pro řídící proměnnou cyklu for ve skriptu
    >
    > Je to tak a kompletní, nebo je to ještě složitější?
    >
    > ------------------------------------------------------------------------
    > Tomáš Vognar
     
     
    24. září 2011 17:47
  • Zdravím všechny dřívější rádce !

    Po 3,5 letech potřebuji skript doplnit o jeden výpočet a už v tom zase tápu. Jedná se mi o sečtení cifer dvouciferného čísla, viz funkční příklad z ruky:

    set /a s=43
    set /a l=%s:~0,1%+%s:~1%
    echo %l%
    
    7

    Já to ale potřebuji ve skriptu v cyklu for:

    @echo off
    setlocal ENABLEDELAYEDEXPANSION
    set site=10 14 20 24 30 40 50 
    for %%s in (%site%) do (
    	set /a l=!s:~0,1!+!s:~1!
    	echo !l!
    )

    a to už nefunguje. Odkaz už také není funkční.

    Prosím tedy o radu a děkuji předem.

    Místo Windows XP už mám 8.1.


    Tomáš Vognar

    5. března 2015 13:52
  • Retezcove operace nefunguji s ridicimi promennymi cyklu. Pouzij pom. promennou

    for %%s in (%site%) do (
    	set POM=%%s
    	echo pocitam !POM:~0,1!+!POM:~1!
    	set /a l=!POM:~0,1!+!POM:~1!
    	echo !l!
    
    )

    MP

    5. března 2015 14:05
    Moderátor
  • Bezva, to funguje !

    Tomáš Vognar

    5. března 2015 14:14