Writing data using batch files - batch-file

So I am using the "#echo" command to write data files in batch.
"#echo set value=%userinput%>> test2.bat"
The idea of this is to create a batch file named test2.bat that has 1 line of text which should be "set value=%userinput%" user input being what ever the user typed. The problem is that when every the users input is only a single digit such as 1, 2, 3, and so fourth, the command won't function. If I turned the 1 into a 10, then the command works but if I chose anything between 1 and 9 it just won't work the way it should. Could someone explain to me why? and recommended work around?

>> test2.bat echo set value=%userinput%
A digit directly before a redirector redirects that device number (0=stdin, 1=stdout, 2=stderr, 3-9 undefined)
If you want exactly one line in your file, use >. >> appends to any existing data; > recreates the file.
unless you want the literal % in your file, when you should use %% in place of each literal % you are using. %var% evaluates var, %%var%% puts the literal %var% because % "escapes" %

Due to redirection notation being in the form 1> & 2> your output is eating those input digits. I think that it is easier to wrap your echo command into parentheses to prevent it instead of placing the redirection notation at the start of the line.
#(echo set value=%userinput%)>>test2.bat

Related

How to escape escape "=" or Equal to sign in batch script in a double quote string

SET "gmail5=https://mail.google.com/mail/u/5/?tab=wm&ogbl#inbox"
echo %gmail5%
The output is
H:\local\CODE\Batch scripting\powershell\Config>.\test.bat
H:\local\CODE\Batch scripting\powershell\Config>SET "gmail5=https://mail.google.com/mail/u/5/?tab=wm&ogbl#inbox"
H:\local\CODE\Batch scripting\powershell\Config>echo https://mail.google.com/mail/u/5/?tab=wm & ogbl#inbox
https://mail.google.com/mail/u/5/?tab=wm
'ogbl#inbox' is not recognized as an internal or external command,
operable program or batch file.
I checked the StackOverflow most of the post said that anything in "" is escaped along with =. I cannot figure out,why it gets recognized in echo. My use case is to use these strings in another batch script for vdesk.
vdesk create:4
vdesk on:1 run:%gmail5%
Batch uses & to separate different commands on one line. It does not assume that "..." is a string - it might be, however unlikely, that the " is a legitimate character as a command parameter.
Hence, you need to escape the & with a caret (^) which should work with all "awkward" characters except % for which the escape is % itself.
the thing you are trying to accomplish can be done in following way,your code was all right except every time when you print special characters use ^ or Cmd will confuse it for &(And) operater.
#echo off
SET "gmail5=https://mail.google.com/mail/u/5/?tab=wm^&ogbl#inbox"
echo %gmail5%
pause >nul

batch file to create and write to VBScript file

I am creating a batch script that creates and writes to a VBScript. I am writing to the file like this:
echo (code for vbscript) >> [name of vbscript].vbs
However, there is one part of the code that is troubling me:
echo If Len(m) > 1 then >> sys.vbs
Since the code itself has a > symbol in it, the batch file interprets it as me trying to write to the VBScript and cuts off the code, but that is not the case. I want the code to say If Len(m) > 1 Then but instead it just says If Len(m) then.
I already tried working around this by modifying the code to say:
echo if NOT Len(m) < 1 then >> sys.vbs
but that does not work either. If I do that, then it omits the whole line of code altogether.
I'm sorry if I didn't explain this problem well enough, it's hard to describe.
<, > and >> are redirection operators in batch. As #rojo already pointed out in the comments you need to escape them with a caret (^) if you want to echo them as literal characters in the output file:
echo If Len(m) ^> 1 Then >> sys.vbs
Using double quotes around the echoed string does not work in this case, because echo includes the double quotes in the output.
However, I agree with #Tomalak that you may want to reconsider your approach. Generating VBScript from a batch file on the fly is usually not a good/clean way of solving whatever problem you have on your hands.

How to pass a parameter to a batch file containing a % without it 'breaking'?

The Problem
In a main batch file, values are pulled from a .txt file (and SET as values of variables within this batch file). These values may each contain % characters.
These are read from the .txt file with no issues. However, when a variable with a value containing a % character is passed to a second batch file, the second batch file interprets any % characters as a variable expansion. (Note: There is no control over the second batch file.)
Example
echo %PERCENTVARIABLE%
Output: I%LOVE%PERCENT%CHARACTERS%
When passed to a second file and then echo'ed, would (probably) become IPERCENT, as it interprets %LOVE% and %CHARACTERS% as unset variables.
Research
I found the syntax to find and replace elements within a string in a batch file, as I thought I could potentially replace a % character with %% in order to escape it. However I cannot get it to work.
The syntax is -
set string=This is my string to work with.
set string=%string:work=play%
echo %string%
Where the output would then be This is my string to play with..
Questions
Is it possible to escape % characters using the find and replace syntax
in a variable? (If not, is there another way?)
Is it advisable to do so? (Could using these escape characters cause any issue in the second batch file which (as mentioned above) we would have no control over?)
Is there another way to handle this issue, if the above is not possible?
There are no simple rules that can be applied in all situations.
There are a few issues that make working with string literals in parameters difficult:
Poison characters like &, |, etc. must be escaped or quoted. Escaping is difficult because it can be confusing as to how many times to escape. So the recommendation is to usually quote the string.
Token delimiters like <space>, <tab>, =, ; and , cannot be included in a parameter value unless it is quoted.
A CALL to a script will double any quoted % characters, and there is no way to prevent this. Executing a script without CALL will not double the % characters. But if a script calls another script and expects control to be returned, then CALL must be used.
So we have a catch-22: On the one hand, we want to quote parameters to protect against poison characters and spaces (token delimiters). But to protect percents we don't want to quote.
The only reliable method to reliably pass string literals without concern of value corruption is to pass them by reference via environment variables.
The value to be passed should be stored in an environment value. Quotes and/or escapes and/or percent doubling is used to get the necessary characters in the value, but it is very manageable.
The name of the variable is passed in as a parameter.
The script accesses the value via delayed expansion. For example, if the first parameter is the name of a variable containing the value, then it is accessed as !%1!. Delayed expansion must be enabled before that syntax can be used - simply issue setlocal enableDelayedExpansion.
The beauty of delayed expansion is you never have to worry about corruption of poison characters, spaces, or percents when the variable is expanded.
Here is an example that shows how the following string literal can be passed to a subroutine
"<%|,;^> This & that!" & the other thing! <%|,;^>
#echo off
setlocal enableDelayedExpansion
set "parm1="^<%%^|,;^^^^^> This ^& that^^!" & the other thing^! <%%|,;^^^>"
echo The value before CALL is !parm1!
call :test parm1
exit /b
:test
echo The value after CALL is !%1!
-- OUTPUT --
The value before CALL is "<%|,;^> This & that!" & the other thing! <%|,;^>
The value after CALL is "<%|,;^> This & that!" & the other thing! <%|,;^>
But you state that you have no control over the 2nd called script. So the above elegant solution won't work for you.
If you were to show the code of the 2nd script, and show exactly what value you were trying to pass, then I might be able to give a solution that would work in that isolated situation. But there are some values that simply cannot be passed unless delayed expansion is used with variable names. (Actually, another option is to put the value in a file and read the value from the file, but that also requires change to your 2nd script)
may be...?
input.txt
I%LOVE%PERCENT%CHARACTERS%
batch1.bat
#echo off
setlocal enableDelayedExpansion
set/P var=<input.txt
echo(In batch 1 var content: %var%
set "var=!var:%%=%%%%!"
call batch2.bat "%var%"
endlocal
exit/B
batch2.bat
#echo off
set "var=%~1"
echo(In batch 2 var content: %var%
exit/B

echo in cmd file produces incorrect results

My .cmd file contains:
set /A "#zz+=1"
set #zz
echo:"%%#zz%%"
Produces:
#zz=4
"%#zz%"
The set #zz shows the variable being properly populated, but echo acts as though it is not there. Curiously, the commands work fine when run from the command prompt.
Actually, batch is doing exactly what it's supposed to. While the normal escape character in batch is ^, you escape % in batch scripts like %%, so you're telling the script to print a literal %, then the string #zz, then another literal %.
If you really want to echo %4%, you need three % signs on each side: echo:"%%%#zz%%%"
This tells batch to print a literal %, then the value of %#zz%, and then another literal %.

Storing multi-word strings to a file

I've recently been trying to make a program to simply store text to a file for later viewing, storing it as a .rar file for security against those who don't understand how to extract the text from the .rar (i.e. the less "techy" people)...
I have, however, encountered an error in the program that results in the <word> not expected at this time followed by the .exe closing when I input add/<word> <word>... (i.e. any multi-word string with spaces in between the words [add/<word>, however, does function properly]).
Is there a special rule that must be followed for storing multi-word strings to a .rar or a file in general (I do, however, know that there is a rule for creating/renaming folders/directories)?
The Program Segment:
:command
cls
set /p journal=<journal.rar
echo %journal%
echo.
set /p command=What would you like to do?
cls
if %command%==exit exit
if %command%==help goto help
if %command%==delete echo START; > journal.rar
if %command:~0,4%==add/ echo "%journal%""%command:~4%;" > journal.rar
if %command:~0,5%==edit/ echo %journal:%command:~5%=%;" > journal.rar
goto command
Excuse me. Your question is not clear. There are several confusing points in it, like "followed by the .exe closing" (which .exe is closing?), and the fact that your question is NOT related to .rar files in any way, nor to "storing multi-word strings". However, I can see the following points in it:
When a variable value is expanded with percent signs this way: %command% you must be aware that the variable is first expanded and then the resulting line is parsed. This mean that the value of the variable may introduce errors in the line. For example, in this line: if %command%==exit exit, if the value of command variable is add/one two three, then the line that is parsed is this: if add/one two three==exit exit that, of course, issue an error! (type if /? for further details).
The way to avoid this problem is enclosing both the variable and the comparison value in quotes; this way, if the value have several words with spaces, the whole value is grouped in the IF command for comparison purposes: if "%command%" == "exit" exit. This must be done in every IF command that use the value of the variable.
In the following line:
if %command:~0,5%==edit/ echo %journal:%command:~5%=%;" > journal.rar
you must be aware that the line is parsed from left to right; this means that you can not nest a %variable% expansion inside another one. The way to solve this problem is first complete a %normal% variable expansion, and then a !delayed! variable expansion that will take the previous expanded value. To do that, insert this line at beginning of your program:
setlocal EnableDelayedExpansion
and change previous line by this one:
if "%command:~0,5%" == "edit/" echo !journal:%command:~5%=!;" > journal.rar
For further details, type set /? and carefully read the sections about "delayed expansion".
Here is a sample that can accept multiple words:
set "command="
set /p "command=What would you like to do? "
cls
if /i "%command%"=="have lunch" goto :food

Resources