batch-filecmd

chcp command changes the piping behavior


There is a script cat.bat emulating unix cat: it reads from input stream and then write into output stream:

@echo off
for /f "tolens=1* delims=:" %%a in ('findstr  /n "^"') do (
  echo(%%b)
)

I can use it in two manners with the same result:

type textfile | cat.bat
cat.bat < textfile

If I insert line chcp>nul before for loop then only the first form (with |) works. The second one (using <) outputs nothing.

Why could this be? And how to achieve unified behavior?


Solution

  • It's a strange behavior, I can't explain it, but I can circumvent it.

    Using find instead of findstr solves the problem.

    @echo off
    chcp > NUL
    
    setlocal DisableDelayedExpansion
    for /F "delims="  %%a in ('find /n /v ""') do (
        set "line=%%a"
        setlocal EnableDelayedExpansion
        set "line=!line:*]=!"
        echo(!line!
        endlocal
    )
    

    I suppose the chcp simply flushes the input stream, but only when the input comes from a redirect. But FIND has the special ability to reset a file redirection, each time it's called.

    test.bat

    @echo off
    chcp
    
    echo Read from stdin with findstr
    findstr  /n "^"
    echo(
    echo Read from stdin with find
    find /n /v ""
    

    Test with: type text.txt | test.bat

    Aktive Codepage: 850.
    Read from stdin with findstr
    1:Line1
    2:Line2

    Read from stdin with find

    Test with: test.bat < text.txt

    Aktive Codepage: 850.
    Read from stdin with findstr

    Read from stdin with find
    [1]Line1
    [2]Line2