Search code examples
batch-filecmdcall

Problem escaping '>' characters when using 'Call'


This code should output >>> without a linefeed, but it just doesn't work.

@if not "%~1"=="" (
    @goto :%~1
    @goto :eof
)
@echo off
setlocal enabledelayedexpansion

call test.bat echonoln "^>^>^>"
pause
goto :eof

:echonoln
set text=%~2
<nul set /p a=%text%
goto :eof

I also tried to replace <nul set /p a=%text% with echo | set /p a=%text%.

I used jeb's method but now there is no '!'.

@echo off
if not "%~1"=="" (
    goto :%~1
)

setlocal enabledelayedexpansion
call "%~f0" echolnln "Hi^^!"
pause
goto :eof

:echolnln
set "text=%~2"
echo.%text%
echo.
goto :eof

Note: it delayed expansion must be enabled.


Solution

  • Your problem is not the escaping, it's the using in the line set text=%~2 and <nul set /p a=%text%, because the special characters are handled there, too.
    You can solve it by using quotes.

    Change it to:

    @echo off
    if not "%~1"=="" (
        goto :%~1
    )
    
    setlocal EnableDelayedExpansion
    call "%~f0" echonoln ">>>Hi^!"
    pause
    goto :eof
    
    :echonoln
    setlocal DisableDelayedExpansion
    set "text=%~2"
    <nul set /p "=%text%"
    endlocal
    goto :eof
    

    Btw. CALL text escaping is nasty and for some combinations it's even impossible.
    It's better not to use text at all with CALL, it's better to use variable names instead, then there is no need for escaping in the call.

    setlocal DisableDelayedExpansion
    set "myText=caret^ exclam! other>&|%%"
    call "%~f0" echonoln myText
    ...
    
    :echonoln
    setlocal EnableDelayedExpansion
    set /p ".=!%~2!"