using powershell inside batch file to add floating numbers from text file - windows

i have a text file logging timestamps from ffprobe on video durations of some video files, which that text file looks like this:
14.068700
5.043011
84.071967
5.043011
104.058600
5.043011
134.055234
5.056000 ....
I am trying to add these up, since batch files do not allow for floating numbers i chose to use powershell. here is my following code:
set total=0
for /f "tokens=*" %%x in (timestamps.txt) do (
set item=%%x
echo !item!
for /f "delims=." %%i in ('powershell %total% + %item%') DO SET total=%%i
echo %total%
)
but again it seems cause it is a floating number i am unable to do something like
SET /a total=%total% + %total%
so that i can not add that as a variable in this line:
powershell %total% + %item%
I have tried every combo i can think of with no luck, lots of searches and nothing comes back.
any idea how to do this or is there a better way to add up all these in pure batch ?

a pure Powershell solution would have been much simpler, but seeing as you require batch-file with powershell:
#echo off
setlocal enabledelayedexpansion & set nums=
for /f "usebackq delims=" %%x in ("timestamps.txt") do set nums=!nums!%%x+
for /f "delims=" %%i in ('powershell %nums:~0,-1%') do set "total=%%i"
echo Total: %total%
We just append all the numbers with the operator + to a variable, then pass that variable to powershell and get the result.
Note! delayedexpansion is needed because we are setting
or by utilizing powershell to do all the work and simply assign the result to the variable:
#echo off
for /f "delims=" %%i in ('"powershell -command (Get-Content -Path "timestamps.txt" ^| Measure-Object -Sum^).Sum"') do set "total=%%i"
echo Total: %total%

so this is what i came up with, not as elegant as it possibly can be BUT it is working. Wish it was a bit quicker but PowerShell slows things down a bit but definitely worth it!
its crazy to think when doing dos they never thought of using floating numbers, lol
anyways here is code:
set seconds=0
set item=0
for /f "tokens=*" %%t in (%filename%_copy_two%fileextension%) do (
set item=%%t
for /f %%i in ('powershell !item!+!seconds!') do (set seconds=%%i)
)
for /f %%i in ('powershell -NoP "[Math]::Round(!seconds!/ 60,2)"') do (set minutes=%%i)
set HH=00
for /f "tokens=1 delims=." %%r in ('echo %minutes%') do set min=%%r
for /f "tokens=2 delims=." %%p in ('echo %minutes%') do set sec=%%p
IF %sec% GTR 60 (
set /a newSec=!sec!-60
if !newSec! lss 10 set newSec=0!newSec!
set /a newMin=1 + !min!
if !newMin! lss 10 set newMin=0!newMin!
) else (
set /a newMin=!min!
set /a newSec=!sec!
)
IF %newMin% LSS 60 (
if !newMin! lss 10 set newMin=0!newMin!
set MM=!newMin!
if !newSec! lss 10 set newSec=0!newSec!
set SS=!newSec!
GOTO playlistTotal
)
IF %newMin% GEQ 60 IF %newMin% LSS 120 (
set /a MM=!newMin!-60
if !MM! lss 10 set MM=0!MM!
set /a HH=01
set SS=!newSec!
GOTO playlistTotal
)
IF %newMin% GEQ 120 IF %newMin% LSS 180 (
set /a MM=!newMin!-120
if !MM! lss 10 set MM=0!MM!
set /a HH=02
set SS=!newSec!
GOTO playlistTotal
)
IF %newMin% GEQ 120 IF %newMin% LSS 240 (
set /a MM=!newMin!-180
if !MM! lss 10 set MM=0!MM!
set /a HH=03
set SS=!newSec!
GOTO playlistTotal
)
IF !newMin! EQU 240 (
set /a MM=!newMin!-240
if !MM! lss 10 set MM=0!MM!
set /a HH=04
set SS=!newSec!
GOTO playlistTotal
)
IF %newMin% Gtr 240 (
ECHO We do not suggest a single playlist over 4 hours.
echo Please Go back edit your list to be shorter.
ECHO And just append to it
del %filename%_copy%fileextension%
del %filename%_copy_two%fileextension%
GOTO editPlaylist
)
:playlistTotal
del %filename%_copy%fileextension%
del %filename%_copy_two%fileextension%
echo.
Echo Playlist a total duration of = !HH!:!MM!:!SS!
echo.
IF !newMin! EQU 240 (
set /a MM=!newMin!-240
if !MM! lss 10 set MM=0!MM!
set /a HH=04
set SS=!newSec!
GOTO playlistTotal
)
IF %newMin% Gtr 240 (
ECHO We do not suggest a single playlist over 4 hours.
echo Please Go back edit your list to be shorter.
ECHO And just append to it
del %filename%_copy%fileextension%
del %filename%_copy_two%fileextension%
GOTO editPlaylist
)
:playlistTotal
del %filename%_copy%fileextension%
del %filename%_copy_two%fileextension%
echo.
Echo Playlist has a total duration of= !HH!:!MM!:!SS!
echo.
I hope this helps someone out! kind of stinks i cant ask a question for 6 months for this question considering there is NOT solution that I can find that met me OP
And once again I posted my solution after a question which I try to do every time, have a great day!
EDIT: thanks to #Gerhard
I have changed to this, but leaving the code here in case someone needs for a similar issue in a different way.
for /f "delims=" %%i in ('"powershell -command (Get-Content -Path "%filename%_copy_two%fileextension%" ^| Measure-Object -Sum^).Sum"') do set "seconds=%%i"
for /f %%i in ('powershell -NoP "[Math]::Round(!seconds!/ 60,2)"') do (set minutes=%%i)
Then keeping the same as is till someone posts a better solution.

You can achieve this in a very simple and pure Batch file that run much faster than any PS:
#echo off
setlocal
set /A factor=1000000, total=0
for /F "tokens=1,2 delims=." %%a in (timestamps.txt) do set /A total+=%%a*factor+1%%b-factor
echo %total:~0,-6%.%total:~-6%
Of course, this solution is so simple because it assumes that all input numbers have 6 decimals! If this is not the case, then the code should be modified accordingly...

Related

cmd: How to include a maximum run time in the for loop?

I have a long list and i want to split it up in parts that will wait for an external trigger to go on.
At first I tried a for loop that did 100 rows per run.
But because of differences in workload on the pc the amount of time it takes varies.
So i was wondering, is it possible to loop the FOR statement for a set time.
But could not find any example.
After adding the suggestion stephan made to use a for loop with delayed expansion, it now works.
How to include a maximum run time in the for loop?
'''
#ECHO OFF
SETLOCAL enabledelayedexpansion
CLS
set ENDTIME=!TIME!
set function_endtime=!ENDTIME!
for /F "tokens=1-4 delims=:.," %%a in ("%function_endtime%") do (
set /A "start=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
)
:: add 4 seconds to current time as end time
set /A function_endtime=start+(4*100)
:: Format the result for use in if loop
set /A hh=function_endtime/(60*60*100),rest=function_endtime%%(60*60*100), mm=rest/(60*100), rest%%=60*100, ss=rest/100, cc=rest%%100
if %hh% lss 10 set hh=0%hh%
if %mm% lss 10 set mm=0%mm%
if %ss% lss 10 set ss=0%ss%
if %cc% lss 10 set cc=0%cc%
set function_endtime=%hh%:%mm%:%ss%.%cc%
echo Finish: %function_endtime% now: %time%
FOR /F "tokens=1,2 delims=," %%A IN (C:\test.txt) DO (
echo %%A %%B
set "last_value=%%B"
if "!time!" geq "%function_endtime%" goto :done
)
:done
echo %time%
'''
you can't put code between goto and the :label I guess you completely misinterpreted my comment. Your code should look like:
...
FOR /F "tokens=1,2 delims=," %%A IN (C:\test.txt) DO (
echo %%A %%B
set "last_value=%%B"
if "!time!" geq "%function_endtime%" goto :done
)
:done
...
(without any testing or checking your logic)

Batch file script to remove lines in text file when count greater than >

I have text documents filled with URLs and when I count the number of lines inside the file, as soon as the line count is greater than 1000, I want to delete the lines which follow those, keeping the first 1000 lines.
This is my code but I can't figure out what I am doing wrong.
Create a text.txt file with this script location and put over 1000 lines of junk into it to test.
#ECHO OFF & setLocal EnableDelayedExpansion
color 0A
%*
SET root_path=%~dp0
set text_name=text.txt
set text_name_output=output_text.txt
set max_line_count=1000
set /a counter=0
for /f %%a in (%root_path%%text_name%) do (
set /a counter += 1
echo Number of lines: !counter!
if !counter! LSS %max_line_count% (
echo less than
) else (
echo more than so delete these line numbers
(for /f "tokens=1,* delims=[]" %%a in ('type %root_path%%text_name%^|find /v /n ""') do (
echo/%%a|findstr /x "!counter!" >nul || echo/%%b
))>%root_path%%text_name_output%
)
)
pause
Using a batch file for this task is absolutely not appropriate, however, here's a basic structure which should do what you asked, however slow that may be.
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "InFile=text.txt"
Set "LineLimit=1000"
Set "OutFile=output_text.txt"
If Not Exist "%InFile%" Exit /B
(
For /F Delims^= %%G In (
'%SystemRoot%\System32\findstr.exe /N /R "^" "%InFile%" 2^>NUL'
) Do (
Set "}=%%G"
Set /A "{=%%G" 2>NUL
SetLocal EnableDelayedExpansion
If !{! Gtr %LineLimit% (
EndLocal
GoTo Next
)
Echo(!}:*:=!
EndLocal
)
) 1>"%OutFile%"
:Next
I figured it out if the text or document has more than 1000 lines then delete all lines that follow.
#ECHO OFF & setLocal EnableDelayedExpansion
color 0A
%*
SET root_path=%~dp0
set text_name=text.txt
set text_name_output=output_text.txt
set max_line_count=1000
set /a counter=0
for /f %%a in (%root_path%%text_name%) do set /a counter+=1
set /a "counter=%counter%-%max_line_count%"
more +%counter% "%root_path%%text_name%" >"%root_path%%text_name_output%"
move /y "%root_path%%text_name_output%" "%root_path%%text_name%" >nul
pause
It sounds like you want a head program. This is easily done in PowerShell.
Get-Content -Path '.\text.txt' -First 1000 >'.\output_text.txt'
If you must run from cmd.exe, the following might be used.
powershell -NoLogo -NoProfile -Command ^
"Get-Content -Path '.\text.txt' -First 1000 >'.\output_text.txt'"

Find the biggest of 4 numbers in Windows Batch scripting

I am trying to find the biggest of 4 numbers in batch scripting but it is not working.
The GTR command is not getting executed.
From this line it never gets executed if !Counter_Senior! gtr !Max_Age! (
I'm new to batch scripting, I am not sure about alignment and spacing. please help me through.
echo off
setlocal enabledelayedexpansion
set /a Counter_Child=1
set /a Counter_Senior=2
set /a Counter_Older_adult=0
set /a Counter_Young_adult=3
set /a Max_Age=%counter_Child%
echo maximum age is %Max_Age%
if !Counter_Senior! gtr !Max_Age! (
set Max_Age=%Counter_Senior%
if !Counter_Older_adult! gtr !Max_Age! (
set Max_Age=%Counter_Older_adult%
if !%Counter_Young_adult! gtr !Max_Age! (
set Max_Age=%Counter_Young_adult%
time /t
echo Maximum age is %Max_Age%
goto:EOF
)
)
)
if !Counter_Older_adult! gtr !Max_Age! (
set %Max_Age%=%Counter_Older_adult%
if !%Counter_Young_adult! gtr !Max_Age! (
set %Max_Age%=%Counter_Young_adult%
echo Maximum age is %Max_Age%
goto:EOF
)
)
if !%Counter_Young_adult! gtr !Max_Age! (
set %Max_Age%=%Counter_Young_adult%
echo Maximum age is %Max_Age%
goto:EOF
)
echo Maximum age is %Max_Age%
goto:EOF
Your code seems way too complicated. Try this:
echo off
set Counter_Child=1
set Counter_Senior=2
set Counter_Older_adult=0
set Counter_Young_adult=3
set Max_Age=%Counter_Child%
IF %Counter_Senior% GTR %Max_Age% SET Max_Age=%Counter_Senior%
IF %Counter_Older_adult% GTR %Max_Age% SET Max_Age=%Counter_Older_adult%
IF %Counter_Young_adult% GTR %Max_Age% SET Max_Age=%Counter_Young_adult%
echo maximum age is %Max_Age%
If you only want the maximum value of the four Counter variables then you could use this:
For /F "Tokens=2 Delims==" %%A In ('Set Counter_'
) Do If %%A GEq !Max_Age! Set/A Max_Age=%%A
[Edit]And for the scenario suggested by Anders…
For %%A In (
%Counter_Child% %Counter_Senior% %Counter_Older_adult% %Counter_Young_adult%
) Do If %%A GEq !Max_Age! Set/A Max_Age=%%A
There are (at least) two problems with your code:
You are using goto:EOF inside a if and that quits the entire batch file.
In some places you incorrectly used set %Max_Age%=.. instead of set Max_Age=..
Your code is also overcomplicated and can be reduced to something simpler like the answer posted by MichaelS.
If you want to print specific information when a change is made you can use a generic sub procedure:
#echo off
goto Start
:CheckAge
setlocal enableextensions enabledelayedexpansion
set newage=!%1!
if %newage% gtr %Max_Age% (
echo %1 is older than %Max_Age%, the new maximum is %newage%
set Max_Age=%newage%
)
endlocal & set Max_Age=%Max_Age%
goto :EOF
:Start
set Counter_Child=1
set Counter_Senior=2
set Counter_Older_adult=0
set Counter_Young_adult=3
set Max_Age=0
call :CheckAge Counter_Child
call :CheckAge Counter_Senior
call :CheckAge Counter_Older_adult
call :CheckAge Counter_Young_adult
echo Maximum age is %Max_Age%

Windows Batch File can't use variable in for syntax

I want to use a variable skip parameter in for loop, but it won't let me do it.
Here is my code
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /p testcase=<testcases.txt
set /a end=%testcase%*13
for /L %%P IN (1,13,%end%) DO (
set skip=skip=%%P
echo !skip!
set vidx=0
for /f "%skip%" %%A in (testcases.txt) do (
set /a vidx=!vidx! + 1
set var!vidx!=%%A
)
)
Here skip is skip=1, but it doesn't skip any line. When I replace it with skip=1. then it works fine, but I want to skip variable no. of lines in each iteration. Please help.
I think with this logic the only option is a subroutine:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /p testcase=<testcases.txt
set /a end=%testcase%*13
for /L %%P IN (1,13,%end%) DO (
set skip=skip=%%P
echo !skip!
set vidx=0
call :innerFor %%P
)
exit /b 0
:innerFor
for /f "skip=%~1" %%A in (testcases.txt) do (
set /a vidx=!vidx! + 1
set var!vidx!=%%A
)
exit /b 0
parametrization of FOR /F options is a little bit tricky..
Though I have no the content of your files I cant test if this works correctly .

CMD date change log

I am making a program and it has a change log. The programs change log must say the version and then show how many days ago it was. So it should say:
[2013/03/19, 2 days ago]
I used this code:
set versionreleasedate1=2013/03/17
set /a verionday=%versionreleasedate1%-%date%
echo Version: 1.0 BETA [2013/03/19, %verionday% days ago]
but I know that the date it is dividing because cmd thinks that the \ symbol is devide buy I want that a little sepricator for the date.
So it would work like this
set /a var1=2013/03/17-%date% (todays date)
and echo how many days ago. Any help would be awesome thanks.
This works for my machine, and hopefully for yours:
#echo off &setlocal
set "versionreleasedate1=2013/03/17"
set "versionreleasetime1=00:00:00,00"
call :GetInternational
call :GetSecs "%versionreleasedate1%" "%versionreleasetime1%" startsec
call :GetSecs "%date%" "%time%" stopsec
set /a versionday=(%stopsec%-%startsec%)/86400
echo Version: 1.0 BETA [%versionreleasedate1%, %versionday% days ago]
goto :eof
:GetInternational
:: Sets a bundle of variables by reading the registry settings
for /f "tokens=1,2*" %%a in (' reg query "HKCU\Control Panel\International"^|find "REG_SZ" ') do set "%%a=%%c"
goto :eof
:GetSecs "dateIn" "timeIn" secondsOut
:: Output: Seconds elapsed since 1th Jan. 1970 00:00:00
:: http://www.dostips.com/forum/viewtopic.php?p=6450#p6450
setlocal
set "dateIn=%~1"
for /f "tokens=2" %%i in ("%dateIn%") do set "dateIn=%%i"
for /f "tokens=1-3 delims=%sDate%" %%a in ("%dateIn%") do (
if %iDate%==0 set /a mm=100%%a%%100,dd=100%%b%%100,yy=10000%%c%%10000
if %iDate%==1 set /a dd=100%%a%%100,mm=100%%b%%100,yy=10000%%c%%10000
if %iDate%==2 set /a yy=10000%%a%%10000,mm=100%%b%%100,dd=100%%c%%100
)
for /f "tokens=1-3 delims=%sTime%%sDecimal% " %%a in ("%~2") do (
set "hh=%%a"
set "nn=%%b"
set "ss=%%c"
)
if 1%hh% lss 20 set hh=0%hh%
if "%nn:~2,1%" equ "p" if "%hh%" neq "12" (set "hh=1%hh%" &set /a hh-=88)
if "%nn:~2,1%" equ "a" if "%hh%" equ "12" set "hh=00"
if "%nn:~2,1%" geq "a" set "nn=%nn:~0,2%"
set /a hh=100%hh%%%100,nn=100%nn%%%100,ss=100%ss%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2,j=j/5+dd+y*365+y/4-y/100+y/400-2472633,j=j*86400+hh*3600+nn*60+ss
endlocal &set "%~3=%j%"
goto :eof
endlocal
%versionreleasedate1% & %versionreleasetime1% must be in the same format like %date% & %time% on your machine!

Resources