for %1 %%i in (*.*) do [...] not working

Discussion in 'Support' started by roytam1, Apr 15, 2010.

  1. roytam1

    Message Count:
    43
    In CMD, I can place %1 in for statement so that I can control for loop to recursive or not, for example (sizes.bat):
    Code:
    @echo off
    
    set TOTALSIZE=0
    for %1 %%i in (*.*) do call :add %%~zi
    echo %TOTALSIZE%
    set TOTALSIZE=
    goto :EOF
    
    
    :add
     set /A TOTALSIZE+=%1
    
    but with TCC, it shows usage of for statement no matter %1 is set or not.
  2. samintz Scott Mintz

    Message Count:
    756
    not working

    I haven't tried this but I suspect due to the complex nature of FOR's
    syntax, something is getting tripped up.

    Change this:
    set TOTALSIZE=0
    for %1 %%i in (*.*) do call :add %%~zi
    echo %TOTALSIZE%

    to this:
    set TOTALSIZE=0
    set foreach=for %1 %%i in (*.*) do call :add %%~zi
    %foreach
    echo %TOTALSIZE

    -Scott

    roytam1 <> wrote on 04/15/2010 06:57:16 AM:


    not.
  3. roytam1

    Message Count:
    43
    Re: not working

    It doesn't work.

    BTW the rewrited script won't work in CMD any longer.
    I want to keep CMD compatibility of scripts.
  4. vefatica

    Message Count:
    3,988
    not working

    I think the problem is the way TCC parses the command line. AFAIK, you can't
    use a variable before FOR's loop variable. It's the "%1" that's the problem.
    You **can** do that with CMD. Apparently (and again unlike CMD) you also can't
    do this:

    set command=FOR /L
    %command %i in (1,1,2) echo %i

    You can, however, use an alias (forget CMD compatibility):

    IFF "%1" == "/R"
    ALIAS myfor FOR /R
    ELSE
    ALIAS myfor FOR
    ENDIFF
    myfor ...

    And this, though awkward, works:

    v:\> set command=for /l

    v:\> %command %%i in (1,1,2) echo %%i
    1
    2

    On Thu, 15 Apr 2010 12:30:10 -0400, samintz <> wrote:

    |I haven't tried this but I suspect due to the complex nature of FOR's
    |syntax, something is getting tripped up.
    |
    |Change this:
    |set TOTALSIZE=0
    |for %1 %%i in (*.*) do call :add %%~zi
    |echo %TOTALSIZE%
    |
    |to this:
    |set TOTALSIZE=0
    |set foreach=for %1 %%i in (*.*) do call :add %%~zi
    |%foreach
    |echo %TOTALSIZE
    |
    |-Scott
    |
    |roytam1 <> wrote on 04/15/2010 06:57:16 AM:
    |
    |
    |
    |---Quote---
    |> In CMD, I can place %1 in for statement so that I can control for
    |> loop to recursive or not, for example (sizes.bat):
    |>
    |> Code:
    |> ---------
    |> @echo off
    |>
    |> set TOTALSIZE=0
    |> for %1 %%i in (*.*) do call :add %%~zi
    |> echo %TOTALSIZE%
    |> set TOTALSIZE> goto :EOF
    |>
    |>
    |> :add
    |> set /A TOTALSIZE+=%1
    |> ---------
    |> but with TCC, it shows usage of for statement no matter %1 is set or
    |---End Quote---
    |not.
    |
    |
    |
    |
    --
    - Vince
  5. samintz Scott Mintz

    Message Count:
    756
    Re: not working

    The issue has to do with delayed parsing and FOR's loop variable. When
    TCC is parsing the FOR statement it is interpreting %1 as the loop
    variable. It has no way of knowing you meant to use %i instead. The
    following syntax, while not CMD compatible, does work in TCC. Note both
    the use of backticks and double %'s to enable the functionality you're
    trying for.

    @echo off

    set TOTALSIZE=0
    set foreach=`for %1 %%i in (*.*) do call :add %%@filesize[%%i]`
    echo "%foreach"
    %foreach
    echo %TOTALSIZE
    set TOTALSIZEgoto :EOF


    :add
    set /A TOTALSIZE+=%1

    As an alternative using purely TCC syntax:
    echo %@filesize[*.*]

    or

    echo %@eval[%@execstr[4,dir /s /u2]]

    -Scott


    roytam1 <> wrote on 04/15/2010 12:37:36 PM:


  6. samintz Scott Mintz

    Message Count:
    756
    Re: not working

    Actually, I left out the recurse option:

    echo %@filesize[*]

    or

    echo %@filesize[/S *]

    -Scott

    samintz <> wrote on 04/15/2010 04:26:10 PM:



  7. roytam1

    Message Count:
    43
    Re: not working

    but allowing %1 ~ %9 and %* for use as FOR variable breaks compatibility with CMD.

    and the example is just a minimal test case for reproducing the issue.
    my full script look like this:
    Code:
    @echo off
    setlocal EnableDelayedExpansion
    set REDUSIZE=0
    
    for %1 %%i in (*.jpeg;*.jpg) do call :optjpeg "%%~i"
    echo Done. %REDUSIZE% bytes freed.
    
    rem clean up
    set REDUSIZE=
    set rpath=
    set FSIZE=
    SET SIZEDIFF=
    GOTO :EOF
    
    rem sub optjpeg(filename)
    :optjpeg
    SET SIZEDIFF=0
    call :rpath "%~1"
    jpegtran.exe -optimize "%~1" "%~1.new"
    if errorlevel 1 del "%~1.new" & echo %rpath% ... jpegtran internal error. Skipped.
    ujpg.exe "%~1.new" > nul 2>&1
    call :fsize "%~1.new"
    SET /A SIZEDIFF=%~z1-%FSIZE%
    if %FSIZE% EQU 0 del "%~1.new" & echo %rpath% ... Zero byte output. Skipped.
    if %SIZEDIFF% LSS 0 del "%~1.new" & echo %rpath% ... Output [%FSIZE%] is larger than original [%~z1]. Skipped.
    if %SIZEDIFF% EQU 0 del "%~1.new" & echo %rpath% ... Original and output has same size [%~z1]. Skipped.
    
    if exist "%~1.new" call :overwrite "%~1"
    GOTO :EOF
    
    rem sub overwrite(filename)
    :overwrite
     set /A REDUSIZE+=%SIZEDIFF%
     echo %rpath% ... from %~z1 to %FSIZE% [%SIZEDIFF%].
      touch -r "%~1" "%~1.new"
     move /y "%~1.new" "%~1"
    GOTO :EOF
    
    rem sub rpath(filename) OUT: %rpath%
    :rpath
     SET rpath=%~1
     set rpath=!rpath:%CD%\=!
    GOTO :EOF
    
    rem sub fsize(filename) OUT: %FSIZE%
    :fsize
     IF EXIST %1 (
      SET FSIZE=%~z1
     ) ELSE (
      SET FSIZE=0
     )
    GOTO :EOF
    
    endlocal
    
  8. roytam1

    Message Count:
    43
    Re: not working

    but replace %%~zi with %%@filesize[%%i] works.
    TCC kills %%~zi here.
    Code:
    @echo off
    
    set TOTALSIZE=0
    set FORSW=for %1
    %FORSW% %%i in (*.*) do call :add %%@filesize[%%i]
    echo %TOTALSIZE%
    set TOTALSIZE=
    goto :EOF
    
    
    :add
     set /A TOTALSIZE+=%1
  9. samintz Scott Mintz

    Message Count:
    756
    Re: not working

    I have not tested this script, but this is an equivilent TCC script to
    what you are attempting to do in CMD:

    Code:
    @echo off
    setlocal
    set REDUSIZE=0
    do jpg in %1 *.jpeg;*.jpg
            f:\app_re~1\jpegtran.exe -optimize "%jpg" "%jpg.new"
            iff errorlevel 1 then
                    del "%jpg.new"
                    echo %@filename[%jpg] ... jpegtran internal error. 
    Skipped.
                    iterate
            endiff
            f:\app_re~1\ujpg.exe "%jpg.new" > nul 2>&1
            set fsize=%@filesize[%jpg.new]
            iff %fsize LE 0 then
                    echo %@filename[%jpg] ... Zero byte output. Skipped.
                    iterate
            elseiff %fsize GT %@filesize[%jpg] then
                    echo %@filename[%jpg] ... Output [%fsize] is larger than 
    original [%@filesize[%jpg]]. Skipped.
                    iterate
            elseiff %fsize EQ %@filesize[%jpg] then
                    echo %@filename[%jpg] ... Original and output have same 
    size [%@filesize[%jpg]]. Skipped.
                    iterate
            endiff
            set SIZEDIFF=%@eval[%@filesize[%jpg] - %fsize]
            set /A REDUSIZE+=%SIZEDIFF
            echo %@filename[%jpg] ... from %@filesize[%jpg] to %fsize 
    [%SIZEDIFF].
            touch /r "%jpg" "%jpg.new"
            move /y "%jpg.new" "%jpg"
    enddo
    echo Done. %REDUSIZE bytes freed.
    endlocal
    
    -Scott

    roytam1 <> wrote on 04/15/2010 08:35:45 PM:



    Skipped.

  10. roytam1

    Message Count:
    43
    Re: not working

    but your script, I can't supply /r in %1 for recursive iteration, and it won't show relative path.

    and I wonder why people there always rewrite one's script to BTM even if he/she wants CMD compatibility.
  11. Steve Fabian

    Message Count:
    2,757
    Re: not working

    | but your script, I can't supply /r in %1 for recursive iteration,
    | and it won't show relative path.

    You need to use /S as the first (and only) parameter of the posted batch
    program so it would iterate through all subdirectories of the starting path.
    What do you mean by "relative path"? If %fullpath is the full pathname
    of a file, and the file is located in a subdirectory of %ref_path, the value
    of the function %@replace[%ref_path,,%fullpath] is the path of the file
    relative to directory %ref_path.

    | and I wonder why people there always rewrite one's script to BTM
    | even if he/she wants CMD compatibility.

    Sometimes it is a lot easier to have separate batch files for CMD.EXE
    and for TCC.EXE. Many of us (including myself) never learned how to use
    CMD.EXE, having "grown up" with the JP Software command processors, we never
    downgraded.
    --
    HTH, Steve
  12. roytam1

    Message Count:
    43
    In website, JP Software claims "Upwardly compatible with CMD.EXE with literally thousands of additions".
    But actually it doesn't, and failing in most powerful part in CMD: FOR command:
    - wrongly parsing FOR variable with arguments and SET variables.
    - killing extended FOR variables(%%~{*} variables, see FOR /? in CMD for details) if using SET variable to store FOR command.
    and one offing this topic:
    - improper MBCS support.

    How JP Software claim "compatible with CMD.EXE" with these incompatibilities?

    I'm really not trying to criticizing TCC or JP Software, both Take Command(/LE) and TCC(/LE) are still excellent products. But I feel disappointed for JP Software not responding my questions and shifting off problem to "no in-house wide char developers" but not providing ANSI version again as a workaround. 4NT/TCC switched to Unicode only version, but not taking extra care to ANSI-Unicode/Unicode-ANSI conversion and brings trouble to users.
  13. rconn Administrator

    Message Count:
    5,854
    not working

    Well, no -- IMHO this is *not* an issue. You're apparently upset that FOR
    will recognize something other than a single alphabetic character as a FOR
    variable; most users consider this a feature. If you don't duplicate your
    variable names, it will not be a problem.


    As I said, we do not support DBCS environments. When we *did* (in older
    ANSI versions of 4NT), our Asian sales never amounted to more than 0.1% of
    the total. Given this, it makes no financial sense for us to divert limited
    resources to support imaginary non-paying customers.


    We never claimed 100% compatibility -- an obvious impossibility, given that
    (1) different versions of CMD.EXE are incompatible, and (2) it's impossible
    to add features without introducing some level of incompatibility. Given
    the choice of supporting undocumented CMD.EXE bugs (like the FOR or IF
    termination in batch files) or providing additional features (like the batch
    debugger and ON ERROR), we'll go with the features.

    Rex Conn
    JP Software
  14. roytam1

    Message Count:
    43
    Re: not working

    I didn't. But instead, I'm pleased that I can use other than single letter as FOR variable.

    But in other side, FOR it trying to use command line arguments(%1 ~ %9, %*) and variable that should evaluated first (%var%) as FOR variable, but not evaluate things(arguments, %var%) first and then execute the FOR statement. Does it make sense?


    then the internal CHCP is nothing other than a joke.
    PLEASE NOTE the >127 part(for example: ¼ Ê Á ð Æ à æ Ì ñ Ç á È ò â ¶ Ö) in ANSI codepages (CP 437/850/etc.) will use 2 bytes to store when using UTF-8(CP 65001).

    without proper support, even UTF-8 support is broken too.

    As I said in that thread, you just not taking care of wchar_t/char count of MultiByteToWideChar and WideCharToMultiByte(IF you use WinAPI to deal with Unicode-ANSI/ANSI-Unicode conversion), which is trivial to fix.

    for unknown undocumented features/bugs, YES we can live without it.
    but for documented behavior or well known behavior, you should make it work BECAUSE you claim the compatibility with CMD.

    But BTW I don't think Microsoft will change the behavior (both documented and undocumented) in CMD in the future because Microsoft is trying to push their PowerShell to users.
  15. rconn Administrator

    Message Count:
    5,854
    Re: not working

    FOR supports all variable types, *except* as the first variable following
    the FOR, where FOR expects only a FOR variable. This is necessary due to
    the much more complex nature of TCC's FOR than CMD's simplistic FOR. TCC
    also doesn't expand the entire line before it's even recognized as a FOR (as
    does CMD), so you don't need the doubled %%'s to prevent premature
    expansion.

    Rex Conn
    JP Software
  16. rconn Administrator

    Message Count:
    5,854
    Re: not working


    Well, OK, if you're ignoring the vast majority of code pages which are *not*
    DBCS.


    There is no UTF-8 support in Windows. A few Windows apps have some custom
    support for UTF-8, but Windows itself is all UTF-16.

    Rex Conn
    JP Software
  17. samintz Scott Mintz

    Message Count:
    756
    Re: not working

    DO uses /S for recursing into subdirectories. And there is no real
    benefit to bending over backwards to make sure your script works in CMD
    and TCC. If this is a shared script then either make it TCC/LE compatible
    or get licenses for everyone that uses it.

    Ultimately, if you need CMD to run your script from TCC you can always do
    CMD /C cmdscript.bat

    Relative paths are on the suggestion list (at least I know I've made that
    suggestion in the past). Nonetheless, it is still possible to create
    relative paths easily.

    set slen=%@len[%_CWD]
    do jpg in %1 *.jpg;*.jpeg
    echo jpg = "%jpg"
    echo name = %@filename[%jpg]
    echo rel path = .%@right[-%slen,%@full[%jpg]]
    enddo

    -Scott

    roytam1 <> wrote on 04/16/2010 09:13:53 PM:


  18. roytam1

    Message Count:
    43
    Re: not working

    These are real test cases to checking TCC's CMD compatibility.

    By the way, about the full script I posted in this thread, I found that "setlocal EnableDelayedExpansion" cannot be use for temporarily enabling Delayed Variable Expansion function.

    I know that there is an option for enable it permanently (requires restart) but I want to use it temporarily inside setlocal/endlocal scope.

    and the Delayed Variable string substitution (!var:from=[to(can be empty)]!) is not working (even if I enabled it in option and restarted).
  19. roytam1

    Message Count:
    43
  20. samintz Scott Mintz

    Message Count:
    756
    Re: not working

    Again if 100% compatibility is necessary then just use CMD to run the
    script.

    CMD /c script.bat

    -Scott

    roytam1 <> wrote on 04/19/2010 12:57:52 PM:


    compatible

    do

    that

    scope.

Share This Page

Users found this page by searching for:

  1. for %i in

    ,
  2. for %1 in

    ,
  3. for %1

    ,
  4. for %i in (,
  5. for 1 in,
  6. for %1 in (,
  7. for %1 do,
  8. for %%a in (%1) do