Escape angle brackets in a Windows command prompt

WindowsCmdEscaping

Windows Problem Overview


I need to echo a string containing angle brackets (< and >) to a file on a Windows machine. Basically what I want to do is the following:
echo some string < with angle > brackets >>myfile.txt

This doesn't work since the command interpreter gets confused with the angle brackets. I could quote the whole string like this:
echo "some string < with angle > brackets" >>myfile.txt

But then I have double quotes in my file that I don't want.

Escaping the brackets ala unix doesn't work either:
echo some string \< with angle \> brackets >>myfile.txt

Ideas?

Windows Solutions


Solution 1 - Windows

The Windows escape character is ^, for some reason.

echo some string ^< with angle ^> brackets >>myfile.txt

Solution 2 - Windows

True, the official escape character is ^, but be careful because sometimes you need three ^ characters. This is just sometimes:

C:\WINDOWS> echo ^<html^>
<html>

C:\WINDOWS> echo ^<html^> | sort
The syntax of the command is incorrect.

C:\WINDOWS> echo ^^^<html^^^> | sort
<html>

C:\WINDOWS> echo ^^^<html^^^>
^<html^>

One trick out of this nonsense is to use a command other than echo to do the output and quote with double quotes:

C:\WINDOWS> set/p _="<html>" <nul
<html>
C:\WINDOWS> set/p _="<html>" <nul | sort
<html>

Note that this will not preserve leading spaces on the prompt text.

Solution 3 - Windows

There are methods that avoid ^ escape sequences.

You could use variables with delayed expansion. Below is a small batch script demonstration

@echo off
setlocal enableDelayedExpansion
set "line=<html>"
echo !line!

Or you could use a FOR /F loop. From the command line:

for /f "delims=" %A in ("<html>") do @echo %~A

Or from a batch script:

@echo off
for /f "delims=" %%A in ("<html>") do echo %%~A

The reason these methods work is because both delayed expansion and FOR variable expansion occur after special operators like <, >, &, |, &&, || are parsed. See How does the Windows Command Interpreter (CMD.EXE) parse scripts? for more info.


sin3.14 points out that pipes may require multiple escapes. For example:

echo ^^^<html^^^>|findstr .

The reason pipes require multiple escapes is because each side of the pipe is executed in a new CMD process, so the line gets parsed multiple times. See https://stackoverflow.com/q/8192318/1012053 for an explanation of many awkward consequences of Window's pipe implementation.

There is another method to avoid multiple escapes when using pipes. You can explicitly instantiate your own CMD process, and protect the single escape with quotes:

cmd /c "echo ^<html^>"|findstr .

If you want to use the delayed expansion technique to avoid escapes, then there are even more surprises (You might not be surprised if you are an expert on the design of CMD.EXE, but there is no official MicroSoft documentation that explains this stuff)

Remember that each side of the pipe gets executed in its own CMD.EXE process, but the process does not inherit the delayed expansion state - it defaults to OFF. So you must explicitly instantiate your own CMD.EXE process and use the /V:ON option to enable delayed expansion.

@echo off
setlocal disableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo !test!|findstr .

Note that delayed expansion is OFF in the parent batch script.

But all hell breaks loose if delayed expansion is enabled in the parent script. The following does not work:

@echo off
setlocal enableDelayedExpansion
set "line=<html>"
REM - the following command fails
cmd /v:on /c echo !test!|findstr .

The problem is that !test! is expanded in the parent script, so the new CMD process is trying to parse unprotected < and >.

You could escape the !, but that can get tricky, because it depends on whether the ! is quoted or not.

If not quoted, then double escape is required:

@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo ^^!test^^!|findstr .

If quoted, then a single escape is used:

@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c "echo ^!test^!"|findstr .

But there is a surprising trick that avoids all escapes - enclosing the left side of the pipe prevents the parent script from expanding !test! prematurely:

@echo off
setlocal enableDelayedExpansion
set "line=<html>"
(cmd /v:on /c echo !test!)|findstr .

But I suppose even that is not a free lunch, because the batch parser introduces an extra (perhaps unwanted) space at the end when parentheses are used.

Aint batch scripting fun ;-)

Solution 4 - Windows

In order to use special characters, such as '>' on Windows with echo, you need to place a special escape character before it.

For instance

echo A->B

will no work since '>' has to be escaped by '^':

 echo A-^>B

See also escape sequences. enter image description here

There is a short batch file, which prints a basic set of special character and their escape sequences.

Solution 5 - Windows

> Escaping the brackets ala unix doesn't > work either:

> echo some string < with > angle \> brackets >>myfile.txt

The backslash would be considered the start of a absolute pathname.

Solution 6 - Windows

You can also use double quotes to escape special characters...

echo some string "<" with angle ">" brackets >>myfile.txt

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJasonView Question on Stackoverflow
Solution 1 - WindowsTim RobinsonView Answer on Stackoverflow
Solution 2 - Windowssin3.14View Answer on Stackoverflow
Solution 3 - WindowsdbenhamView Answer on Stackoverflow
Solution 4 - WindowsorbitcowboyView Answer on Stackoverflow
Solution 5 - WindowsJames CurranView Answer on Stackoverflow
Solution 6 - WindowsaalaapView Answer on Stackoverflow