I've started utilizing ANSI color codes in batch scripts for Windows 10. Today I discovered that suddenly colors stopped working, and I traced it to a for
command with an embedded MSYS command. For example:
@echo off
echo ^[[92mThis works.^[[0m
for %%f in (x) do @echo ^[[93mThis also works.^[[0m
for /l %%f in (1,1,1) do @echo ^[[94mThis too works.^[[0m
for /f "tokens=*" %%f in ('date /t') do @echo ^[[95mThis one works.^[[0m
for /f "tokens=*" %%f in ('sha1sum.exe ^< NUL') do @echo ^[[91mThis one DOES NOT work.^[[0m
echo ^[[92mThis works.^[[0m
(Note: Where you see "^[" needs to be a single ESC character, ASCII 27, instead. E.g., type <C-V><ESC>
in Vim's insert mode.)
In my case, sha1sum.exe refers to C:\Program Files\Git\usr\bin\sha1sum.exe
from Git for Windows. We all know batch scripts/cmd.exe have their own wizardry about them, but I can't think of an explanation for this. Is it somehow toggling color interpretation off for the duration of the command line? And if so would there be a way to force it back on?
APPEND:
It's worth noting that it seems to affect the entire "command line", meaning if you have nested ifs and fors using parenthesis the entire bit wrapped in parenthesis appears to be affected.
This is just a confirmation and some workarounds
Sample code
@echo off
setlocal enableextensions disabledelayedexpansion
for /f %%a in ('
forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo 0x1B"
') do set "ESC=%%a"
echo %ESC%[91mRed
echo %ESC%[92mGreen
echo %ESC%[0mNormal
echo A simple base test
for /f "tokens=1,2" %%a in ('
echo 0000000000000000000000000000000000000000 %~f0
') do echo(.... %ESC%[92m%%a %ESC%[91m%%b %ESC%[0m
echo Git sha1sum
for /f "tokens=1,2" %%a in ('
E:\portable\bin\git\64\usr\bin\sha1sum.exe "%~f0"
') do echo(.... %ESC%[92m%%a %ESC%[91m%%b %ESC%[0m
echo Git sha1sum DELAYED
for /f "tokens=1,2" %%a in ('
E:\portable\bin\git\64\usr\bin\sha1sum.exe "%~f0"
') do set "output=%ESC%[92m%%a %ESC%[91m%%b %ESC%[0m"
echo(.... %output%
echo GNUPG sha1sum
rem ftp://ftp.gnupg.org/gcrypt/binary/sha1sum.exe
rem https://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000184.html
for /f "tokens=1,2" %%a in ('
E:\portable\bin\sha1sum.exe "%~f0"
') do echo(.... %ESC%[92m%%a %ESC%[91m%%b %ESC%[0m
echo %ESC%[90mDone%ESC%[0m
As seen, you can deal with a simple case, but the git sha1sum
executable interferes with the console.
Some alternatives
The easiest one is to send the output to a file and then use the for /f
to process the file
Here you have information on a way to deal with the problem (you will need to compile code)
Select a different tool for the work.