Want to print single digit value in txt file using Batch script - batch-file

I am trying to write a single digit value in a txt file using Batch script.
Here is my sample code:
set no=1
set flag=7
echo FlagStatus=%flag%>>Output.txt
echo[>>Output.txt
echo Number=%no%>>Output.txt
But this is not working properly. The line with value 1 prints without value and if I use any value other than 1, it doesn't even prints the line
Here is the output of this code:
Number=
I am excepting following output:
FlagStatus=1
Number=7
I will be grateful for your help. thanks

With your numbers directly in front of the redirection > you give the command to use a specific output stream, instead of stdout.
echo FlagStatus=1>>Output.txt
is executed as
echo FlagStatus= 1>>Output.txt
This means, redirect the stdout of the echo command to Output.txt.
In case of flag=2 it becomes
redirect the stderr of the echo command to Output.txt, but echo does output nothing to stderr at all.
A simple solution is to use a block instead, it's faster, more readable and avoids problems with stream handles.
set no=1
set flag=7
(
echo FlagStatus=%flag%
echo(
echo Number=%no%
) >>Output.txt

Related

batch script: The process tried to write to a nonexistent pipe

#echo off
(for /f "skip=1 tokens=3,5,11" %%a in (Data.txt) do (if /i "%%c"=="%1" (if %%b==%2 echo %%a))
echo EXIT
)|Sum.exe
I'm trying to write a simple batch script that would take the .txt file with columns of data (Data.txt), find some values using 'if' and redirect all found values to stdin input of "Sum.exe".
"EXIT" is also redirected as it means that there's no more input to be given.
When I run above code first found value is printed in console and then "The process tried to write to a nonexistent pipe" message error is printed multiple times. Therefore echo EXIT somehow must be messing up with |Sum.exe. How to properly redirect both for and echo Exit into Sum?
EDIT:
Ok, so here's the input part of the Sum program (written in c++)
std::string a;
while (a != "EXIT")
{
std::cin >> a;
if (isNumber(a))
add(sum, std::stoi(a));
}
I added cout to see whether the data was being processed and it seems that the commands in batch script were treted as input aswell.
My first suggestion would be procedure call: call :PROCEDURE. But the call doesn't work with pipe redirection.
For example call :PROCEDURE | SORT return error: Invalid attempt to call batch label outside of batch script.
So I suggest to use input parameter as switch flag to call self batch. For example it would be third parameter: %3. Batch calls itself while third parameter equals x.
So I made this code
#echo off
if "%3"=="x" (%~nx0 %1 %2|sort )& GOTO :EOF
for /f "skip=1 tokens=3,5,11" %%a in (Data.txt) do (
if /i "%%c"=="%1" (if %%b==%2 echo %%a)
echo EXIT
)
I use sort.exe utility in my example. Change it to your sum.exe
To call batch-file use syntax: my_batch.cmd [value11] [value5] x
P.S. I think you do not need word EXIT in output but I left it in example code.

Capturing true STDIN piped to a batch file

I want to access STDIN from inside a batch file after some other commands. I know that the first command in a .BAT file receives STDIN but I want to first run some other commands and then capture STDIN. I also want this to work with streamed STDIN i.e. it is not acceptable to capture STDIN to a file at the start with (see workaround below).
Now, I understand that CON is the "file" representing STDIN and that TYPE CON would output (echo) STDIN. This does not seem to work at all inside a batch file. Indeed, it appears not to represent STDIN but user/host input by keyboard.
test.bat
TYPE CON > output.txt
Test run:
C:>TYPE myfile.txt | test.bat
Expected result: myfile.txt is copied into output.txt.
Actual result: The batch waits for user input (ignores what is piped to it) and writes user input typed on the keyboard to output.txt.
Workaround
As a workaround: the following test.bat works but does not support streamed input (e.g. from a tail command):
findstr "^" STDIN.txt
:: I can now run some other commands
:: And finally access my STDIN via STDIN.txt
TYPE STDIN.txt | AWK /e/ > output.txt
UPDATE: Back Story:
I have a neat CMD which uses powershell to download (via HTTP) an arbitrary .ps1 script (like a package manager would) and execute it on the fly. If I call REMEXEC.bat mymodule foo bar it loads and executes mymodule.ps1 with the parameters foo and bar.
This works wonderfully for every scenario except piped, streamed input. Using the findstr "^" works for piped input but not for an open stream. Using say AWK /.*/ as the first line of my BAT gets me that streamed input but just pushes the problem down the road.
Ultimately I want a something.bat which looks like this (pseudocode):
downloadPSModule( "http://myrepo.com/modules/%1.ps1" )
STDIN | executePSModule %2 %3 %4
The catch 22 is that downloadPSModule happens BEFORE executePSModule and thus has no access to STDIN (a privelege reserved for the first line of a BAT).
If you need to retrieve input from console or isolate reading from the stdin stream to not consume piped data, I would try directly reading from console with something like
#echo off
setlocal enableextensions disabledelayedexpansion
rem Part that reads from console, not piped input
< con (
set "data="
set /p "data=Type something: "
)
echo(
echo You have typed: [%data%]
echo(
rem Part that reads piped input
find /v ""
When executed
W:\>type test.cmd | test.cmd
Type something: this is a test
You have typed: [this is a test]
#echo off
setlocal enableextensions disabledelayedexpansion
rem Part that reads from console, not piped input
< con (
set "data="
set /p "data=Type something: "
)
echo(
echo You have typed: [%data%]
echo(
rem Part that reads piped input
find /v ""

cmd, write and read from txt

i was toying around with cmd a bit and wanted to write a little application which involves a simple feature to read a counter from a txt file, then work with it and at the end raise the counter by one.
set /p x=<file.txt
...
set /a y=x+1
echo %y%>file.txt
Problem is it always returns "ECHO ist eingeschaltet (ON)." which translates to ECHO is turned on (ON) for some reason. Could somebody please explain where it comes from and how to fix it? I dont need anything fancy. I just want it to work and know where my mistake is.
At first, I want to show you how your echo command line should look like:
> "file.txt" echo(%y%
Here is your original line of code again:
echo %y%>file.txt
The reason for the unexpected output ECHO is on./ECHO is off. is because the echo command does not receive anything to echo (type echo /? and read the help text to learn what on/off means). Supposing y carries the value 2, the line expands to:
echo 2>file.txt
The number 2 here is not taken to be echoed here, it is consumed by the redirection instead; according to the article Redirection, 2> constitutes a redirection operator, telling to redirect the stream with the handle 2 (STDERR) to the given file. Such a handle can reach from 0 to 9.
There are some options to overcome that problem:
inserting a SPACE in between the echoed text and the redirection operator:
echo %y% >file.txt
the disadvantage is that the SPACE becomes part of the echoed text;
placing parentheses around the echo command:
(echo %y%)>file.txt
placing the redirection part at the beginning of the command line:
>file.txt echo %y%
I prefer the last option as this is the most general and secure solution. In addition, there is still room for improvement:
quote the file path/name to avoid trouble in case it contains white-spaces or other special characters;
use the odd syntax echo( to be able to output everything, even an empty string or literal strings like on, off and /?;
> "file.txt" echo(%y%
Hint:
To see what is actually going on, do not run a batch file by double-clicking on its icon; open a command prompt window and type its (quoted) path, so the window will remain open, showing any command echoes and error messages. In addition, for debugging a batch file, do not put #echo off on top (or comment it out by preceding rem, or use #echo on) in order to see command echoes.
Echo on means that everything that is executed in the batch is also shown in the console. So you see the command and on the following line the result.
You can turn this off with the echo off command or by preceding a # sign before the command you want to hide.
so
::turns of the echo for the remainder of the batch or untill put back on
::the command itself is not shwn because off the #
#echo off
set /p x=<file.txt
...
::the following won't be shown regardless the setting of echo
#set /a y = x+1
echo %y% > file.txt
EDIT after first comment
because your command echo %y%>file.txt doesn't work, you need a space before the > symbol, now you get the result of echo which gives you the current setting of echo
here a working sample, I put everything in one variable for sake of simplicity.
echo off
set /p x =< file.txt
set /a x += 1
echo %x% > file.txt

Batch: Why does appending a textfile write "ECHO is off" instead?

So I wrote a batch that has some code to check how many times it has been run by reading a textfile and then writing back into that textfile the new, increased number.
#ECHO OFF
for /f "delims=" %%x in (TimesRun.txt) do set Build=%%x
set Build=%Build%+1
#echo Build value : %Build%
echo %Build%>>TimesRun.txt
Pause
That does append the textfile allright, but it adds "1+1" to it. Silly me! I forgot to use the /a switch to enable arithmetic operations! But when I change the code accordingly...
#ECHO OFF
for /f "delims=" %%x in (TimesRun.txt) do set Build=%%x
set /a Build=%Build%+1
#echo Build value : %Build%
echo %Build%>>TimesRun.txt
Pause
... something funny happens: Instead of appending my file, ECHO is off. gets written on the console. Now, I know that this usually happens when ECHO is used without text or with an empty variable. I have added the first #echo Build value : %Build% specifically to see whether the variable Build is empty or not; it is not, and the calculation was carried out correctly.
I already figured out that
>>TimesRun.txt (echo %Build%)
does bring the desired result. I still do not understand why
echo %Build%>>TimesRun.txt
does not, however. What am I missing?
You are unintentionally specifying a redirection handle.
Redirection allows you to specify a certain handle that defines what is to be redirected:
0 = STDIN (keyboard input)
1 = STDOUT (text output)
2 = STDERR (error text output)
3 ~ 9 = undefined
For the input redirection operator <, handle 0 is used by default; for the output redirection operators > and >>, the default handle is 1.
You can explicitly specify a handle by putting a single numeric figure in front of the redirection operator; for instance 2> defines to redirect the error text output.
In your echo command line you are doing exactly this unintentionally, when %Build% is a single numberic digit, like 1 for example:
echo 1>>TimesRun.txt
To avoid that, you have the following options:
To reverse the statement so that the redirection definition comes first:
>>TimesRun.txt echo %Build%
This is the most general and secure way of doing redirections.
To enclose the redirected command in parentheses:
(echo %Build%)>>TimesRun.txt
This also works safely.
To put a SPACE in front of the redirection operator:
echo %Build% >>TimesRun.txt
This works too, but the additional SPACE is included in the output of echo.
See also this great post: cmd.exe redirection operators order and position.
Batch file redirection can be customized to specify where you're outputting to.
command 1>file.txt redirects the output of STDOUT to file.txt
command 2>file.txt redirects the output of STDERR to file.txt
Your build value was 1, so you inadvertently told CMD to send the output of echo to TimesRun.txt - when you run echo by itself, it prints it's status (ON or OFF).
You also could have said echo %Build% >>TimesRun.txt and the space would prevent the value of Build from being treated as a redirection command.
The Microsoft article Using command redirection operators explains the 3 standard handles and how to redirect them to another handle, command, device, file or console application.
Redirection of output written to handle 1 - STDOUT - to a file should be done with just
using > ... create file if not already existing or overwrite existing file, or
using >> ... create file if not already existing or append to existing file.
The redirection operators are usually appended at end of a command line. But this is problematic in case of using command ECHO and the string output to STDOUT ends with 1 to 9.
One of several solutions is to specify in this case the redirection at beginning of the command line:
#for /F "delims=" %%x in (TimesRun.txt) do #set Build=%%x
#set /A Build+=1
#echo Build value : %Build%
>>TimesRun.txt echo %Build%
Executing this small batch file without #echo off at top from within a command prompt window shows what Windows command processor executes after preprocessing each line with text file TimesRun.txt containing currently the value 0 or does not exist at all.
echo 1 1>>TimesRun.txt
It can be seen that Windows command interpreter moved the redirection to end of line with inserting a space and 1 left to >>.
With above batch code the line with >> really executed after preprocessing is:
echo 2 1>>TimesRun.txt
Specifying the redirection at end with 1>>, i.e. use in the batch file
echo %Build%1>>TimesRun.txt
is also no good idea as this would result on first run in executing the line:
echo 11 1>>TimesRun.txt
So 11 is written into the file instead of 1. This wrong output could be avoided by inserting a space before >> or 1>>, i.e. use one of those two:
echo %Build% >>TimesRun.txt
echo %Build% 1>>TimesRun.txt
But then the space after %Build% is also written into the file as really executed is:
echo 1 1>>TimesRun.txt
The trailing space would be no problem here, but should be nevertheless avoided.
Note: On using arithmetic operations, i.e. set /A ... any string not being a number or operator is automatically interpreted as variable name and the current value of this variable is used on evaluating the arithmetic expression. Therefore after set /A with environment variable names consisting only of word characters and starting with an alphabetic character as usually used for environment variables no %...% or !...! must be used inside the arithmetic expression. This is explained in help of command SET output into console window on running set /? within a command prompt window.

Redirecting command input using <

Input redirection is working for .exe files or internal windows commands.
app.exe < ListOfNames.txt
sort < input.txt
However it isn't working when I try to redirect it into a batch script.
test.bat :-
#echo off
echo %1 %2
Running it using :-
test.bat<input.txt
where input.txt has two strings.
However, it is working fine for redirecting output even in case of batch scripts.
Is this the expected behavior or I am making some syntax mistake? Is there any other way to read arguments from a file instead of manually parsing it?
Parameters that are provided on the command line are completely different than stdin ( where your redirected input goes). This is true for both batch scripts as well as .exe programs.
Some programs are designed to accept the same values via command line arguments or stdin. But that is not the norm. That is a feature that is provided by the developer of the program.
If you want to read redirected input within a batch script, then you must do one of the following.
To read a single line:
set /p "ln="
echo %ln%
To read all lines in a loop:
for /f "delims=" %%A in ('findstr "^"') do (
echo %%A
)
Additionally to dbenhams answer, you could also read multiple lines with set/p for a input redirection, like myBatch.bat < commands.txt
#echo off
set "line_1="
set "line_2="
set "line_3="
set /p line_1=
set /p line_2=
set /p line_3=
set line_
But this would fail with an input pipe like type commands.txt | myBatch.bat

Resources