batch-filecmd

chcp doesn't work when called from inside 'for /f' loop


I have a script to convert from 1251 code page (ansi) to 866 code page (oem). It takes content of file 'ansi.txt', converts it and then saves to 'oem.txt'

@echo off

chcp 1251
for /f "tokens=*" %%a in (ansi.txt) do (
  call :f_chcp 866
  echo %%a >>oem.txt
  call :f_chcp 1251
)
exit /b

:f_chcp
chcp %1 >nul
exit /b

It works well.

But if I replace "call :f_chcp 866" with just "chcp 866 >nul" it doesn't. In that case it outputs to file using previous value of code page (1251).

Can anyone explain why? Chcp.com is external binary. How is it possible that when it called from inside 'for /f' loop it does no desired effect. However, chcp then still reports that code page has been changed. And what has changed when it called from inside the same loop but being wrapped in subroutine?


Solution

  • It's just the call!
    It works even with a call to an empty function

    @echo off
    
    chcp 1251
    for /f "tokens=*" %%a in (ansi.txt) do (
      chcp 866
      call :activate_chcp_effect
      (echo %%a) >>oem.txt
      chcp 1251
    )
    exit /b
    
    :activate_chcp_effect
    exit /b
    

    And it seems superfluous to switch between code pages in every loop.
    This code snippet only changes the code page in the first loop, and the output file is only opened once.
    This should be much faster.

    set "cp_active="
    chcp 1251 > NUL
    (
      for /f "delims=" %%a in (ansi.txt) do (
        if not defined cp_active (
          set "cp_active=1"
          chcp 866 > NUL
          call :sub
        )
        (echo(%%a)
      )
    ) >oem.txt
    chcp 1251 > NUL