Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can we write a line ending with " 1" into a file using a Windows batch script?

Tags:

batch-file

Short Question

How do I echo the string "foo 1" with the echo command while redirecting its output to a file such that the entire string is written to the file?

C:\>echo foo 1>foo.txt

C:\>type foo.txt
foo

C:\>xxd -g1 a.txt
0000000: 66 6f 6f 20 0d 0a                                foo ..

The above experiment shows that only "foo " is written to the file because the "1" in the command is interpreted to be a part of the redirection operator, 1>. Note that echo foo 1 > foo.txt is not a solution, since it would write "foo 1 " to the file with an unnecessary trailing space in the string.

Long question

Consider the following Windows batch script.

@echo off
call :log "start script"
call :log "foo"
call :log "end script"
goto :eof

:log
echo %~1>>log.txt
goto :eof

When I execute this script, it behaves as desired, i.e. write three lines of log in log.txt.

C:\>foo

C:\>type log.txt
start script
foo
end script

Now consider the following script in which the second line of log has been modified from "foo" to "foo 1".

@echo off
call :log "start script"
call :log "foo 1"
call :log "end script"
goto :eof

:log
echo %~1>>log.txt
goto :eof

This causes a bit of a surprise. As you can see in the output below, we see "foo" instead of "foo 1" in the log file.

C:\Users\pals3\Desktop>foo

C:\Users\pals3\Desktop>type log.txt
start script
foo
end script

It's easy to understand why this happens by removing the first line containing @echo off from the script, and then executing the script.

C:\>foo.cmd

C:\>call :log "start script"

C:\>echo start script 1>>log.txt

C:\>goto :eof

C:\>call :log "foo 1"

C:\>echo foo  1>>log.txt

C:\>goto :eof

C:\>call :log "end script"

C:\>echo end script 1>>log.txt

C:\>goto :eof

C:\>goto :eof

As can be seen here, whenever there is >>log.txt in the script, the command interpreter replaces it with the synonymous syntax, 1>>log.txt. This means our command to log "foo 1" is now executed as echo foo 1>>log.txt, which simply writes "foo" to the log file.

A simple solution is to replace the statement echo %~1>>log.txt in the script with echo %~1 >>log.txt.

@echo off
call :log "start script"
call :log "foo 1"
call :log "end script"
goto :eof

:log
echo %~1 >>log.txt
goto :eof

However, this means each line of log will be suffixed with a space character which is not ideal from a pedantic standpoint, and a little bit confusing when one might want to filter the log file using grep.

C:\>foo

C:\>type log.txt
start script
foo 1
end script

C:\>xxd -g1 log.txt
0000000: 73 74 61 72 74 20 73 63 72 69 70 74 20 0d 0a 66  start script ..f
0000010: 6f 6f 20 31 20 0d 0a 65 6e 64 20 73 63 72 69 70  oo 1 ..end scrip
0000020: 74 20 0d 0a

Is there a way to write the :log subroutine in a manner that it gets rid of the surprise I've mentioned above while not writing an extra space at the end of every line of log?

like image 245
Susam Pal Avatar asked Jun 11 '13 10:06

Susam Pal


People also ask

How do you end a batch file in a script?

Ctrl+C. One of the most universal methods of aborting a batch file, command, or another program while it's running is to press and hold Ctrl + C .

How do I create a line break in batch file?

How can you you insert a newline from your batch file output? You can insert an invisible ascii chr(255) on a separate line which will force a blank new line. Hold down the [alt] key and press 255 on the keypad.

How do you write text in a batch file?

Open a text file, such as a Notepad or WordPad document. Add your commands, starting with @echo [off], followed by, each in a new line, title [title of your batch script], echo [first line], and pause. Save your file with the file extension BAT, for example, test. bat.

How can I read the last 2 lines of a file in batch script?

set /A i-=1 ) set "lastLine[1]=%%a" ) for /L %%i in (%2,-1,1) do if defined lastLine[%%i] echo ! lastLine[%%i]! The version below is more efficient: @echo off setlocal EnableDelayedExpansion rem Tail command in pure Batch, version 2: Tail.


1 Answers

Try with brackets:

@echo off
call :log "start script"
call :log "foo 1"
call :log "end script"
goto :eof

:log
(echo %~1)>>log.txt
goto :eof
like image 154
David Martin Avatar answered Dec 08 '22 13:12

David Martin