Multi-lined command output set as variable - windows

So I've googled and searched stackflow; I think the output for the library I'm using and the way it's structured makes none of the answers work.
I downloaded a windows library called totp2 for command prompt. I am executing the command in my batch file and that works fine, but it wants to return the line I passed.
I'm looking to run the command, and only assign the very last line to a variable; stripping the word OTP: from the last line.
C:\Users\Dan\Desktop\devBash> t2otp.exe QQRZO4QIGPJFXS2QXDIL4JUO2KKQCPTOF2D5AX5M3R2VH5NM2ZUSXIXGP4WPMVTR sha256 6 30
T2OTP v2 - Command line TOTP Generator (c) TOKEN2
Algorithm: sha256
Seed: QQRZO4QIGPJFXS2QXDIL4JUO2KKQCPTOF2D5AX5M3R2VH5NM2ZUSXIXGP4WPMVTR
Interval: 30 seconds
OTP length: 6 digits
OTP: 666323
The above is exactly how it returns the command prompt results, with the code being on line 7 of the command output.
Current Code (hardcoded command just for testing):
For /F "EOL=/" %%A In ('t2otp.exe QQRZO4QIGPJFXS2QXDIL4JUO2KKQCPTOF2D5AX5M3R2VH5NM2ZUSXIXGP4WPMVTR sha256 6 30') Do Set "totp=%%A"
However that returns just OTP:
Current Result:
OTP: 666323
Needed Result:
666323
Any help is really really appreciated.
And yes; it's a demo secret.

For /F "Tokens=2 eol=/" %%A In ('t2otp.exe QQRZO4QIGPJFXS2QXDIL4JUO2KKQCPTOF2D5AX5M3R2VH5NM2ZUSXIXGP4WPMVTR sha256 6 30') Do Set "hash=%%A"
Easy way to feel dumb is when the answer is so simple. Solved.

An even simpler answer is to add "clean" parameter at the end of the command (as described in Token2's documentation):
the last argument is optional, if argument equals to 'loop' , the tool will stay launched recalculating the current OTP until stopped with Ctrl+C, if the argument is 'clean' the tool will produce the OTP only
So the code below:
t2otp.exe QQRZO4QIGPJFXS2QXDIL4JUO2KKQCPTOF2D5AX5M3R2VH5NM2ZUSXIXGP4WPMVTR sha256 6 30 clean
Will give you only the OTP (6 digits in your example)

Related

How to read part of a line in a txt file with a batch script

I'm trying to pull the auxiliary MAC address from a Dell computer in a script, to do that I have the script use Dell's Platform Tag Utility, when I run it
"D:\PlatformTags64W.exe" RAM > D:\mac.txt
The line that I need (3rd line) looks like:
Aux Mac Value .... a1b2c3d4e5f6
To get that line I use the following:
for /f "skip=3 tokens=*" %%c in (mac.txt) do if not defined mac set mac=%%c
What I'm trying to do is only get the a1b2c3d4e5f6 part of it set as %mac% so I can call it later in the script.
I know that powershell would be better for this, but for how it's being used powershell isn't an option.
Change token=*' to tokens=5`.
Token 1 is Aux
Token 2 is Mac
Token 3 is Value
Token 4 is ....
Token 5 is a1b2c3d4e5f6
using the default Space as "delims" (the delimiter set)
.. and better use if not defined mac as you are not setting info in your posted code, so every line following that third line will set mac to the fifth token

get an unknown string between two strings and save it in a var (Windows script)

The thing is that I want to do this JUST by using Windows bash utils (so it can be easily used without other applications like Cygwin/grep on other workstations).
Also this command will be in a larger script that uses the extracted string as a part of a filename.
ex: this is the line in the searched file
" <DataVersion>A0C2</DataVersion>"
A0C2 is the string that I need but it can have a different value like X1Z4 but is always 4 alfanumeric characters long.
<DataVersion> and </DataVersion> are always present.
Also the line may occur more than once but I only need the first to be considered.
I found out in the mean time the answer to my own question.
set ROW=
set VERSION=
for /f %%i in ( 'findstr "<DataVersion>" file.txt' ) do #set ROW=%%i
set VERSION=%ROW:~x,y%
where:
x is the number of characters you want to skip in ROW and
y is the number of characters you want to save in VERSION
so in case
findstr "<DataVersion>" file.txt
returns and sets ROW to this value:
<DataVersion>AX23</DataVersion>
then:
set VERSION=%ROW:~14,4%
will set VERSION to AX23

CMD appears not to recognize variables

CMD does not appear to be recognizing any variable I store using SET. If I run this batch file:
#ECHO off
SET /P name = What is your name?
ECHO %name%
PAUSE
ECHO on
I get the following output:
What is your name? steven
ECHO is off.
Press any key to continue . . .
When I run line 2 and then line 3 from the command prompt, it just prints:
%name%
Do I have something configured incorrectly? Am I correct in thinking that line 2 should create a session variable that should be recognized in line 3?
I searched, but I could only find answers related to variable expansion within IF blocks. This is happening to me outside any IF/FOR/etc blocks.
This is Windows 7, by the way. I'm not sure how much cmd changes from one version of Windows to another.
There must not be any spaces around the equal sign in the set instruction. Change this
SET /P name = What is your name?
into this
SET /P name=What is your name?
and your problem will disappear.
since I can not add any comments yet I have to post a new answer. The information:
"There must not be any spaces around the equal sign in the set instruction."
is only partly correct. To be exact it should say: the equal sign must follow directly after the variable name (in sricks3's case without a space). Whatever comes after the equal sign will be used as input-prompt for the variable including any spaces, so the following code will work as well:
SET /P name= What is your name?

I'm trying to timestamp data from stdin (into a log file) using a Windows Batch file

I'm collecting data from an API using a DOS port of wget to generate data for a log file (which will be analysed at a later date). The API provides all the information I need except a current time (it provides a time at the start of the stream of data but not again after that).
The API provides, typically 10 lines of data initially and then a line every 20-30 seconds.
I'm trying to timestamp this output and copy it to a log file - I don't mind if the timestamp is on the same line as the rest of the output or the line before.
I first started with this batchfile:
addtimes.bat:
#echo off >nul
:start
set /p input="":
echo %time%
echo %input%
goto:start
(called as "wget..... | addtimes.bat > log.log")
However this dropped data comping in - the beginning of many lines of data were lost.
I've looked on here and realised I should use a for loop.
addtimes2.bat:
#echo off
cls
setlocal EnableDelayedExpansion
for /F "tokens=*" %%a in ('more') do (
echo !time! %%a )
)
I've tried with and without Enabling Delayed Expansion.
I don't seem to be able to pass information one line at a time with a different timestamp - all my lines get identical timestamps once I close the datastream.
Typical input data is of the form:
[1,"219","265",14528,1359031137000,1359031137000]
[1,"6594","358",18188,1359031019000,1359031019000]
[1,"690","94",15920,1359031534000,1359031534000]
[1,"25164","102",2129,1359031457000,1359031457000]
[1,"3488","329",2109,1359030868000,1359030868000]
[1,"37247","6",11506,1359031223000,1359031223000]
You may notice there are UTC times in the data but they are not the current time.
I don't believe you can get the result you want using pure native batch. The reason why all your times are the same is that the FOR /F loop does not process any lines of input until the entire input stream has been buffered (the command on the left of the pipe has finished). The FOR /F command waits until all the input has been received, and then dumps every line in one mad rush. If the input stream is large enough, you will get slight variations in time, but nothing that comes close to representing when the original command generated each line.
Here is a hybrid JScript/batch script that does what you want. It works fine as a straight JScript file, but then you need to explictly use CSCRIPT. The hybrid approach makes the utility more convenient.
Call it addtimes.bat and use it just as you were before.
#if (#X)==(#Y) #end /* Harmless hybrid line that begins a JScript comment
::************ Batch portion ***********
#echo off
cscript //E:JScript //nologo "%~f0"
exit /b 0
************* JScript portion **********/
while (!WScript.StdIn.AtEndOfStream) {
var ts = new Date()
var ms = (ts.getTime() % 1000)
WScript.Stdout.WriteLine(
ts.getFullYear() + "-" +
((ts.getMonth()<9)?"0":"") + (ts.getMonth()+1) + "-" +
((ts.getDate()<10)?"0":"") + ts.getDate() + " " +
((ts.getHours()<10)?"0":"") + ts.getHours() + ":" +
((ts.getMinutes()<10)?"0":"") + ts.getMinutes() + ":" +
((ts.getSeconds()<10)?"0":"") + ts.getSeconds() + "." +
((ms<10)?"00":((ms<100)?"0":"")) + ms + " - " +
WScript.StdIn.ReadLine()
);
}
EDIT
wmz has a very clever and dangerous solution. That solution can be simplified - There is no need to muck with Autorun.
Warning - as wmz said, the solution below can have very bad consequences if any line in the output starts with an executable command or program name! I do not recommend actually using this solution, but I find it very interesting.
(echo #prompt $D $T -$S & YourCommandHere )|cmd 2>nul|findstr /rbc:"../../.... ..:..:..\... - " >log.log
The FINDSTR pipe is added to strip out the CMD header info, the initial PROMPT command, and the unwanted blank line that CMD inserts after each "command". The FINDSTR regex may need to change to match the specifics of your chosen prompt and your locale.
Please be warned: this may have a lot of side effects (or may not work at all, or make your system unstable etc.) and is not tested. It's more of exercise in batch than anything else
EDIT: See debenham's answer for refined way of using this idea.
set prompt to time (prompt $T) or date time if you prefer (prompt $D $T). You will have to do it in Autorun key in Registry (HKEY_CURRENT_USER\software\Microsoft\Command Processor) so it's default. If there is no Autorun key, create it (it contains commands executed when cmd prompt is opened)
Start cmd prompt, then pipe output of your command to another cmd.exe, and redirect output of that to file:
more | cmd 2>nul >timestamped.log (you'd use your command where I used more). With more, entering:
this is a message
which was timestamped ^Z
produces following lines in timestamped.log (after two lines with cmd processor version info):
23:19:57,17_this is a message
23:19:59,95_which was timestamped
This works because cmd will try to execute your log entry. This fails (and error message is supressed/sent to nul), but at the same time echoes it together with prompt (time/date).
You must be very careful if your log messages are not quoted (or more generally, if you're not sure of their format, or they are not created under your direct control) - if your line happens to start with a word which is a valid command - it will be executed!

Stop Cygwin from pre-pending "c:\cygdrive' during windows batch command run

Running a friend's batch file with this line
for /F "tokens=1 delims=ΒΆ" %%i in ('which synplify_pro.exe') do set synplify_path=%%~dpi
the var synplify_path is getting set with c:\cygdrive pre-pended.
I just want the windows part.
Is there a way to prevent the pre-pend or get back just the windows part?
Well, you could simply remove that part from the result.
If it is always there after the loop, you could simply cut it off like this:
SET synplify_path=%synplify_path:~11%
where 11 is the length of the string c:\cygdrive. If there's a \ just after the offending string and it needs to be dropped too, make it 12.
Alternatively you could do like this:
SET synplify_path=%synplify_path:c:\cygdrive=%
This will replace all the entries of c:\cygdrive in %synplify_path% with an empty string, i.e. it will simply remove that substring. This method may be better in case there's a chance that c:\cygdrive could be absent from the result for some reason: the method will leave the string unchanged if the string doesn't contain c:\cygdrive.
I'm not sure if you shouldn't actually try to resolve the issue with the command that doesn't like c:\cygdrive in the path, though...

Resources