97

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?

aschipfl
  • 28,946
  • 10
  • 45
  • 77
Jason
  • 1,203
  • 2
  • 10
  • 13

6 Answers6

174

The Windows escape character is ^, for some reason.

echo some string ^< with angle ^> brackets >>myfile.txt
Tim Robinson
  • 50,349
  • 9
  • 115
  • 129
  • 10
    Well, backslash is used for pathnames and double-quote is to wrap filename which have spaces, so there not many character choices left. – James Curran Oct 30 '08 at 20:27
  • This also works for other characters like ampersand (&), thanks. – tenfour Feb 23 '11 at 17:20
  • 2
    Works great! `echo some string ^< with angle ^> brackets >>con` results in: _some string < with angle > brackets_ – Ross Bradbury Jun 16 '11 at 14:33
  • 1
    All because the original pc-dos used backslash for paths and backward compatibility. – Jahmic May 30 '14 at 06:13
  • I suspect it wasn't all that random. My guess is that they wanted to use a character that was unlikely to appear in normal text, so that it didn't cause easily avoidable, but unwanted, character escapes. – David A. Gray Nov 14 '17 at 09:05
25

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.

Itsme2003
  • 121
  • 8
sin3.14
  • 313
  • 3
  • 6
  • 2
    See the 2nd part of [my answer](http://stackoverflow.com/a/26041395/1012053) for an explanation of why pipes require multiple escapes. – dbenham Sep 25 '14 at 15:17
  • 1
    The three `^^^` are also needed to escape commands in Azure DOS/Kudu console. – lionello Feb 13 '17 at 05:46
  • I found this is indeed required when you want to store a value containing pointy brackers in the Azure keyvault through the Azure CLI. – Jaap Sep 09 '20 at 11:45
9

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 Why does delayed expansion fail when inside a piped block of code? 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 ;-)

Community
  • 1
  • 1
dbenham
  • 119,153
  • 25
  • 226
  • 353
3

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.

orbitcowboy
  • 1,190
  • 9
  • 22
0

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.

James Curran
  • 95,648
  • 35
  • 171
  • 253
  • 2
    Absolute pathname relative to the current drive letter... ;) – dalle Oct 31 '08 at 08:54
  • A backslash is not considered the start of an absolute path name inside the text for an echo command -- it's just plain text that gets piped wherever you send it. -- `echo \ ` for example works as expected. -- But yes, the "\" would be an ill choice for a command-line escape character since every command/program that needed a path or filename you'd have to type `\\` instead. – BrainSlugs83 Sep 16 '14 at 19:06
  • 1
    this answer does not offer a solution to the, admittedly vague, question – G-. Jun 06 '16 at 13:35
-3

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

echo some string "<" with angle ">" brackets >>myfile.txt
aalaap
  • 3,693
  • 5
  • 44
  • 54
  • 5
    That does not work. `echo some string "" brackets >>con` results in: _some string "" brackets_ but the OP wants _some string < with angle > brackets_ – Ross Bradbury Jun 16 '11 at 14:31