Sending auto email after uploading of files? - vbscript

There are two files which get uploded in D:\CW-Data\edw location every day between 1am to 1:15 am.
My requirement is to auto send us the email wih the file name when both the files are received.
I tried writing a cript which troughs the lastfile which arrives, but i am not getting the expected result. Please help me out:
My script was
set srcDir=D:\Mitul\Quantum AWR Report_23Apr_3am_2pm
set lastmod=
pushd %srcDir%
for /f "tokens=*" %%a in ('dir /b /od 2^>NUL') do set lastmod=%%a
echo %lastmod%

This is a general purpose script for sending an email.
Original thread at https://groups.google.com/forum/?fromgroups=#!msg/alt.msdos.batch.nt/l_8K11YzS0A/WfbVBoJe-l8J
:: Allows ssl and port 465
:: email.cmd ::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Tom Lavedas, Mod 2.14 to eliminate temporary VBS script file
:: Works with IE5+ (and maybe earlier versions as well)
#echo off
setlocal
:Use command line arguments, if supplied
if [%1] EQU [] goto :Continue
set "Arg=%1"
set "Arg=%Arg::==%"
set "Arg=%Arg:/=%"
set "%Arg%"
shift
goto :Use
:Continue
:: defaults
if not defined From set "From=userid#gmail.com"
if not defined To set "To=you#somemail.com"
if not defined Subj set Subj="email test %date% %time%"
if not defined Body set Body="Did it work? %date% %time%"
if not defined Serv set "Serv=smtp.gmail.com"
if not defined Auth set "Auth=userid#gmail.com"
if not defined Pass set "Pass=password"
if not defined fileattach set "fileattach="
if not defined Port set "Port=465"
if not defined SSL set "SSL=True"
if not defined Timeout set "Timeout=25"
call :send %From% %To% %Subj% %Body% %Serv% %Auth% %Pass% %fileattach%
if %errorlevel% NEQ 0 echo Error: %ErrorLevel%
if %0==%~f0 pause
exit /b %ErrorLevel%
:send
set "cdoSchema=http://schemas.microsoft.com/cdo/configuration"
set arguments="%~1+%~2+%~3+%~4+%~5+%~6+%~7+%~f8"
set VBS=resizeTo 1,1:moveTo 1, 3000:
set VBS=%VBS%set ws=createobject("wscript.shell"):
set VBS=%VBS%with createobject("scripting.filesystemobject")
set VBS=%VBS%Execute ws.ExpandEnvironmentStrings(
set VBS=%VBS%.GetStandardStream(0).readALL):end with:
set "VBS=about:<script type=text/vbs>%VBS%:close</script>"
set "Match=VBScript start"
for /f "delims=[]" %%N in (
'find /n "### %Match% ###" ^<"%~f0"'
) do set "N=%%N"
for /f "tokens=1,2 delims=#" %%A in (
'more +%N% "%~f0" ^| mshta.exe "%VBS%"'
) do #echo %%B & exit /b %%A
exit /b 1 % Error in previous statement %
' ### VBScript start ###
set StdOut=.GetStandardStream(1)
args = Split(%arguments%, "+")
with CreateObject("CDO.Message")
.From = args(0)
.To = args(1)
.Subject = args(2)
.Textbody = args(3)
if args(7) <> "" then .AddAttachment args(7)
with .Configuration.Fields
.Item ("%cdoSchema%/sendusing") = 2 ' not local, smtp
.Item ("%cdoSchema%/smtpserver") = args(4)
.Item ("%cdoSchema%/smtpserverport") = %Port%
.Item ("%cdoSchema%/smtpauthenticate") = 1 ' cdobasic
.Item ("%cdoSchema%/sendusername") = args(5)
.Item ("%cdoSchema%/sendpassword") = args(6)
.Item ("%cdoSchema%/smtpusessl") = %SSL%
.Item ("%cdoSchema%/smtpconnectiontimeout") = %Timeout%
.Update
end with ' Configuration.Fields
On Error Resume Next
.Send
end with ' CDO.Message
if Err.Number = 0 then
sRes = "0#Mail sent without error"
else
sRes = Hex(Err.Number) + "#" + Err.Description
end if
stdout.writeline sRes
' ### VBScript end ### - Must be the end of the batch file

#echo off
setlocal
set srcDir=D:\CW-Data\edw
set file1=whateverthenameofthefirstfileis
set file2=whateverthenameofthesecondfileis
:loop
set /a count=0
for /f %%a in ('dir /b "%srcdir%\%file1%" "%srcdir%\%file2%" 2^>NUL') do set /a count+=1
IF NOT %count%==2 timeout /t 5 >nul&GOTO loop
echo send the email
This will wait for the two files to arrive. If either is missing, timeout 5 seconds and try again.
Don't have enough details to provide more.
Addendum:
If your edition of windows doesn't include timeout, try
IF NOT %count%==2 ping -n 5 127.0.0.1 >nul&GOTO loop

Related

Extract a given ancestor path form a deeper path in Windows CMD

I have no idea how to get what described here using an Win CMD batch script:
pseudo-code
set aPath=C:\just\a\long\path\to\a\file\in\the\file\system
set aDir=file
... some logic here
echo %result%
Should print
C:\just\a\long\path\to\a\file
It should stop at the first occurrence found, but it would be nice to specify also the occurence (optional).
ONLY Windows CMD SOLUTIONS ARE WELCOME no Powershell code nor external tools, please. I'm looking for a pure Windows CMD solution.
I'm not quite sure to what you refer with occurence
Using a shuffle approach and self modifying code to get the dir levels
:: Q:\Test\2019\08\29\SO_57717256.cmd
#Echo off & Setlocal EnableDelayedExpansion
set "aPath=C:\just\a\long\path\to\a\file\in\the\file\system"
set "aDir=file"
echo aPath = %aPath%
echo aDir = %aDir%
::... some logic here
set "intermediate=!apath:*%aDir%=!"
set "result=!aPath:%intermediate%=!"
:: and some vodoo there ;-)
Set i=0
Set "aPath=%aPath:\="&Set /a i+=1&Set "aPath[!i!]=%"
echo result= %result%
for /l %%L in (1,1,%i%) Do if "%aDir%"=="!aPath[%%L]!" (
echo aPath[%%L] = !aPath[%%L]! ^<^<^< matches aDir %aDir%
) else (
echo aPath[%%L] = !aPath[%%L]!
)
Sample output:
> Q:\Test\2019\08\29\SO_57717256.cmd
aPath = C:\just\a\long\path\to\a\file\in\the\file\system
aDir = file
result= C:\just\a\long\path\to\a\file
aPath[1] = just
aPath[2] = a
aPath[3] = long
aPath[4] = path
aPath[5] = to
aPath[6] = a
aPath[7] = file <<< matches aDir file
aPath[8] = in
aPath[9] = the
aPath[10] = file <<< matches aDir file
aPath[11] = system
Here is a little approach using a recursive sub-routine, just for fun:
#echo off
set "aPath=C:\just\a\long\path\to\a\file\in\the\file\system"
set "aDir=file"
set "result=" & set "found="
call :RECURSIVE "%aPath%\."
if defined found echo/%result%
exit /B
:RECURSIVE
if "%~nx1" == "" set "result=%~dp1" & exit /B
call :RECURSIVE "%~dp1."
if defined found (exit /B) else set "result=%result%%~nx1\"
if /I "%~nx1" == "%aDir%" set "found=#" & set "result=%result:~,-1%"
This makes use of the ~ modifiers of command line or sub-routine arguments (parameters), which allow to split a path into pieces.
A simpler approach:
#echo off
setlocal EnableDelayedExpansion
set aPath=C:\just\a\long\path\to\a\file\in\the\file\system\filenot\file\folder
set aDir=file
echo %aPath%
rem This FOR is just for testing; remove it...
for /L %%n in (1,1,3) do (
set "n=%%n"
set "result="
for %%a in ("!aPath:\%aDir%\=" "!") do if !n! gtr 0 set "result=!result!%%~a\%aDir%\" & set /A n-=1
echo %%n: !result:~0,-1!
)
Output example:
C:\just\a\long\path\to\a\file\in\the\file\system\filenot\file\folder
1: C:\just\a\long\path\to\a\file
2: C:\just\a\long\path\to\a\file\in\the\file
3: C:\just\a\long\path\to\a\file\in\the\file\system\filenot\file
EDIT: An even simpler method with the aid of some magic:
#echo off
setlocal EnableDelayedExpansion
set aPath=C:\just\a\long\path\to\a\file\in\the\file\system\filenot\file\folder
set aDir=file
echo %aPath%
set n=%1
set "result="
set "p=%aPath:\=" & (if !n! gtr 0 set "result=!result!\!p!") & (if "!p!" equ "!aDir!" set /A n-=1) & set "p=%"
echo %1: %result:~1%
Output example:
C:\Tests> test 1
C:\just\a\long\path\to\a\file\in\the\file\system\filenot\file\folder
1: C:\just\a\long\path\to\a\file
C:\Tests> test 2
C:\just\a\long\path\to\a\file\in\the\file\system\filenot\file\folder
2: C:\just\a\long\path\to\a\file\in\the\file

when ever a if condition satisfied then we need to pass ctrl+c to stop current item and start the next one in shell script?

Real scenario which I am facing is below,
I am having a bat file to monitor the last updated file based on last modified time and it will tell the user if the file not getting updated with in last 1 min.
2.But my scenario is ,we are using the last modified bat file to monitor the log file update. If the log file not updated in the last 1 min then the script has to send Ctrl + C thru script itself to stop the current test.
Currently when the file not updated with in 1 min then manually we will do Ctrl+C and then the system will ask us like need to exit ? we will say no then it will continue the next test suite.
Currently I am having script to monitor the log file update based on last modified date and time. But i need to automate the steps which i provided in 3.
To check last modified file pls refer below:
copy the below and save it as .bat file with name as checkfolder.
#echo off
:: Wmic removes regional differences
:: XP Pro can have some filename errors due to the short filename bug
setlocal
:: set the number of minutes in the following line
set minutes=1
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%"
set "stamp=%YYYY% %MM% %DD% %HH% %Min%"
call :DateToMinutes %stamp% NowMins
set "name="
for /f "delims=" %%a in ('dir * /a-d /b /od ^|find /v /i "%~nx0"') do set "name=%%a"
if defined name call :CheckMins "%name%"
if %MinsOld% gtr %minutes% echo Folder hasn't been modified in %minutes% minutes & pause
goto :EOF
:CheckMins
set "filestamp="
set "filemins="
set "MinsOld="
set "YY=" & set "YYYY=" & set "MM=" & set "DD="
set "HH=" & set "Min=" & set "Sec=" & set "dt="
set "file=%~sf1"
:: can use CreationDate instead of lastmodified
WMIC DATAFILE WHERE name="%file:\=\\%" get lastmodified | find "." >test.txt
for /f %%a in (rh5.log) do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%"
set "filestamp=%YYYY% %MM% %DD% %HH% %Min%"
del test.txt 2>nul
if not defined yyyy goto :EOF
call :DateToMinutes %filestamp% FileMins
set /a MinsOld=%NowMins%-%FileMins%
goto :EOF
:DateToMinutes
setlocal
set yy=%1&set mm=%2&set dd=%3&set hh=%4&set nn=%5
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
set /a j=j/5+dd+y*365+y/4-y/100+y/400-2472633
if 1%hh% LSS 20 set hh=0%hh%
if /i {%nn:~2,1%} EQU {p} if "%hh%" NEQ "12" set hh=1%hh%&set/a hh-=88
if /i {%nn:~2,1%} EQU {a} if "%hh%" EQU "12" set hh=00
if /i {%nn:~2,1%} GEQ {a} set nn=%nn:~0,2%
set /a hh=100%hh%%%100,nn=100%nn%%%100,j=j*1440+hh*60+nn
endlocal&set %6=%j%&goto :EOF
copy the below and save it as filechecker .bat
#echo off
:loop
call "checkfolder.bat"
timeout /t 60 /nobreak
goto :loop
Then create txt file with the name test.txt. have all the three in same folder and click on checkfolder.bat to verify.
My question is,
Here i got the response as file not modified after that i need to pass ctrl+c thru script and the i have to pass the value as 'n' and hit enter.
if( file not updated)
ctrl+c and then provide n as input to start the next suite
Kindly help me out with this..
see programmatically "press" Ctrl-C / Exit batch inside CALL
Also, you may use a batch and vb hybrid to send keys to whatever window you want... In this sample, keys are sent to current cmd window. You may need to adjust timings to avoid something being echoed between Ctrl+C and s
#echo off
for /L %%a in (1,1,100) do (
echo(Test waiting for Ctrl+C, loop %%a
ping 1.1.1.1 -w 500 -n 1 > NUL
if %%a equ 6 call :sendCTRLC_WAIT
)
echo(This is never reached.
exit/B
rem wait for a second until ctrl-c is sent to this cmd session
:sendCTRLC_WAIT
SetLocal
set "_file1_=%TEMP%\after.vbs"
set "_file2_=%TEMP%\ctrlc.vbs"
>"%_file1_%" (
echo(wScript.Sleep 1300
echo(set oWS = CreateObject("wScript.Shell"^)
echo(oWS.SendKeys "s"
echo(wScript.Sleep 50
echo(oWS.SendKeys "{ENTER}"
)
>"%_file2_%" (
echo(wScript.Sleep 1000
echo(set oWS = CreateObject("wScript.Shell"^)
echo(oWS.SendKeys "^{c}"
)
start /B cmd /C ""%_file1_%"" & rem del /F /Q "%_file1_%" 2>NUL"
start /B cmd /C ""%_file2_%"" & rem del /F /Q "%_file2_%" 2>NUL"
exit/B 0
:sendCTRLC_TESTED
SetLocal
set "_file1_=%TEMP%\after.vbs"
set "_file2_=%TEMP%\ctrlc.vbs"
>"%_file1_%" (
echo(wScript.Sleep 300
echo(set oWS = CreateObject("wScript.Shell"^)
echo(oWS.SendKeys "s"
echo(wScript.Sleep 50
echo(oWS.SendKeys "{ENTER}"
)
>"%_file2_%" (
echo(set oWS = CreateObject("wScript.Shell"^)
echo(oWS.SendKeys "^{c}"
)
start /B cmd /C ""%_file1_%"" & rem del /F /Q "%_file1_%" 2>NUL"
start /B cmd /C ""%_file2_%"" & rem del /F /Q "%_file2_%" 2>NUL"
exit/B 0

Put editable text in command prompt with bat file

I have a bat script that asks for user input with the next line
SET /P returnString=Enter string: %=%
Now I want default input visible on the command line, like:
Enter string: defaultstring
To clarify: I don't want a default value if no input is given, I want the default value visible and editable on the command line, so in the case described above the defaultstring could be replaced for a different text.
Is this possible with SET in a batch file? If not, how could I accomplish this?
Here is a Batch + JScript hybrid script that prompts with a default value.
#if (#CodeSection == #Batch) #then
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: The first line in the script is...
:: in Batch, a valid IF command that does nothing.
:: in JScript, a conditional compilation IF statement that is false.
:: So the following section is omitted until the next "[at]end".
:: Note: the "[at]then" is required for Batch to prevent a syntax error.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Batch Section
#echo off
setlocal
set "Input="
set "Default=Hello World"
title MyUniqueTitle
CScript //E:JScript //Nologo "%~f0" "MyUniqueTitle" "%Default%"
set /p "Input=> Prompt: "
if defined Input set "Input=%Input:"=%"
echo(%Input%
endlocal
exit /b 0
:: End of Batch
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#end
////////////////////////////////////////////////////////////////////////////////
// JScript Section
try
{
var WshShell = WScript.CreateObject('WScript.Shell');
var Title = WScript.Arguments.Item(0);
var Message = WScript.Arguments.Item(1);
WshShell.AppActivate(Title);
WshShell.SendKeys(Message);
WScript.Quit(0);
}
catch(e)
{
WScript.Echo(e);
WScript.Quit(1);
}
WScript.Quit(2);
Well, it's not exactly what you asked for but I think it's better. This will create a browseforfolder dialog and let your user pick what folder to use. In this example r is the return variable from the function. It will return an errorlevel of 0 if a folder is chosen and 1 if the cancel button is hit.
#Echo off
setlocal
Call :BrowseFolder "Enter path to folder" "C:\scripts\" r
echo %r%
echo %errorlevel%
pause
Goto :EOF
:BrowseFolder <Title> <DefaultStartPath> <Return>
setlocal
set vbs="%temp%\_.vbs"
if exist %vbs% del /f /q %vbs%
>%vbs% echo set sh=wscript.CreateObject("Shell.Application")
>>%vbs% echo set f=sh.BrowseForFolder(0,%1,0,%2)
>>%vbs% echo if typename(f)="Nothing" Then
>>%vbs% echo wscript.echo "Dialog Cancelled"
>>%vbs% echo wscript.Quit(1)
>>%vbs% echo end if
>>%vbs% echo set fs=f.Items():set fi=fs.Item()
>>%vbs% echo p=fi.Path:wscript.echo p
for /f "tokens=*" %%a in ('cscript //nologo %vbs%') do set result=%%a
if exist %vbs% del /f /q %vbs%
if "%result%" EQU "Dialog Cancelled" (set a=1) else set a=0
endlocal & set %3=%result% & exit /b %a%

batch - append either date/time of creation or random to end of filename

Damsel in distress needing help with a batch-script.
I have a bunch of files that one system creates. Either in one of 2 directories, or in the directory above that.
The naming is apparently not very important, so It's a bit random.
2 questions for you batch-geniuses out there.
a) How can I append date/time of creation to the end of the filename with a batch-script?
b) How can I append a random filename (so I make the files unique) with a batch-script?
Thanks in advance, dudes and dudettes.
Yours sincerely, the Maclovin!
I have decided in my wisdom to not give a sh*t about the date of creation. I gather it follows the file anyway. What I want to do instead, is to append todays date/time to the file.
This is what I have:
SetLocal EnableDelayedExpansion
set kvitt1="c:\a"
set kvitt2="c:\b"
set tmpDir="c:\temp"
set LASTMOD=
set DATO=%DATE%
set KLOKKE=%TIME%
pause
REM lets go to this directory, and scan for files, and copy to the temp
pushd %kvitt1%
:ONE
for /f "tokens=*" %%a in ('dir /b /od 2^>NUL') do set lastmod=%%a
if "%lastmod%"=="" echo Could not locate files.&goto :TWO
COPY "%Lastmod%" %tmpDir%
pause
#ping 127.0.0.1 -n 2 -w 1000 > nul
#ping 127.0.0.1 -n %1% -w 1000> nul
popd
#ping 127.0.0.1 -n 2 -w 1000 > nul
#ping 127.0.0.1 -n %1% -w 1000> nul
REM Let's go to the next directory, and scan for files to copy to the temp
:TWO
REM Gå til ny nettverksstasjon
pushd %kvitt2%
for /f "tokens=*" %%a in ('dir /b /od 2^>NUL') do set lastmod=%%a
if "%lastmod%"=="" echo Could not locate files.&goto :EOF
COPY "%LASTMOD%" %tmpDir%
pause
#ping 127.0.0.1 -n 2 -w 1000 > nul
#ping 127.0.0.1 -n %1% -w 1000> nul
popd
REM we have copied the files we need, lets skip to the temp directory for renaming and filenaming
pushd %tmpDir%
echo %tmpDir%
pause
REM this is clearly not doing much.
REM gåsetegn foran tmpDir fordi det kan finnes filer med mellomrom. dir/b lister opp filene i mappen, og lagrer det i filelist.txt
dir /b "%tmpDir%" >>filelist.txt
pause
REM går igjennom alle linjene i fillist.txt. %%i inneholder filnavnet
pause
REM for /f %%i in (filelist.txt) do
REM (
REM This is clearly not working
for /F "tokens=2,3,4 delims=/ " %%a in ('date /t') do set filedate=%%a-%%b-%%c
ren %filedate%_"%%T" "%T"
REM ren "%%T" %!random%"%%~nT.kvi")
pause
Try this for a:
ECHO Making the copy...
COPY C:\file.txt c:\file_%time:~0,2%%time:~3,2%%time:~6,2%_%date:~-10,2%%date:~-7,2%%date:~-4,4%.txt
PAUSE
CLS
EXIT
The time parsing is done by (leave out the ECHO if using it within naming a file):
ECHO %time:~0,2%%time:~3,2%%time:~6,2%_%date:~-10,2%%date:~-7,2%%date:~-4,4%
I got this from http://www.ozzu.com/mswindows-forum/can-batch-files-use-date-for-filename-creation-t75600.html where theres a bit more details about it.
As for b, the time here records up to seconds so appending the time will make it unique unless your doing more than 1 per second.
EDIT: This gets only the current date. For the batch rename to file date try this instead:
for /f "delims=|" %%f in ('dir /b C:\temp') do call :runsub %%f
goto EOF
:runsub
set t=%~t1
set t=%t::=%
set t=%t: =%
set t=%t:/=%
set renameto=%~n1-%t%%~x1
Copy %1 %renameto%
:EOF
PAUSE
You can change C:\temp to the path you want to change the files in. Let me know if theres any changes you need.
you are better off using vbscript (or powershell if you have) , rather than batch. this is because date manipulation in batch is dependent on regional settings of your computer. You will have to use tricks like going into the registry and stuff as workaround.
Here's a vbscript you can adapt to your needs.
Set objFS = CreateObject( "Scripting.FileSystemObject" )
strFolder = WScript.Arguments(0)
Set objFolder = objFS.GetFolder(strFolder)
t = Now
strDate = Year(t) & Month(t) & Day(t) & Hour(t) & Minute(t) & Second(t)
' by random number
Randomize
upperbound = 99999
lowerbound = 55555
For Each strFile In objFolder.Files
strExtension = objFS.GetExtensionName( strFile )
strName = objFS.GetBaseName( strFile)
rand = Int((upperbound - lowerbound + 1) * Rnd + lowerbound) 'gen random number
' uncomment to use date
' strFile.Name = strName & strDate & "." & strExtension
' uncomment to use random number of your choosing
' strFile.Name = strName & rand & "." & strExtension
Next

%x was unexpected at this time. batch script

#echo off
for /f "tokens=1,2 delims=," %%x in (my.csv) do (
if %M% LSS %%x set M=%%x
)
echo Max X Value= %M%
Sometimes it works fine, sometimes it fails with following error:
%x was unexpected at this time.
The problem is that you're using %m% inside a for loop. This is evaluated when the loop is read (before any iterations at all). In other words, the entire loop, up to and including the closing parenthesis, is read and evaluated before executing. So %m% will always be it's initial value no matter what you actually set it to within the loop.
An example should hopefully illustrate this:
set val=7
for %%i in (1) do (
set val=99
echo %val%
)
echo %val%
which results in the unexpected (to some):
7
99
simply because the %val% in the first echo statement is interpreted (i.e., the entire for loop is interpreted) before any of it is run.
You need delayed expansion along with something that will force the value of m to be set to the first %%x regardless. Using the setlocal command and !m! instead of %m% will delay evaluation of m until each time the line is executed.
In addition, setting m initially to nothing and forcing it to be %%x when it is nothing will ensure the first value of %%x is loaded into m.
#echo off
setlocal enableextensions enabledelayedexpansion
set m=
for /f "tokens=1,2 delims=," %%x in (my.csv) do (
if "!m!" == "" set m=%%x
if !m! lss %%x set m=%%x
)
echo Max X Value = !m!
endlocal
Using the above code with this my.csv file:
1,a
2,b
10,c
3,d
results in the output of:
Max X Value = 10
as expected or, for your sample data in another comment:
422,34
464,55
455,65
421,88
you get:
Max X Value = 464
There's no environment variable named M set, so when this line is interpreted:
if %M% LSS %%x set M=%%x
After the 1st round of replacements, it looks to the interpreter something like
if LSS %x set M=%x
To avoid the problems that paxdiablo mentions about %M%being expanded only when the loop is first you can use the delayed expansion feature that he discusses, or move testing and setting M to a subroutine that is called from the loop but exists outside the loop so it gets interpreted (and expanded) on each call:
#echo off
set M=
for /f "tokens=1,2 delims=," %%x in (my.csv) do (
call :setmax %%x
)
echo Max X Value= %M%
goto :eof
:setmax
if "%M%" == "" set M=%1
if %M% LSS %1 set M=%1
goto :eof
The problem is in your if %M% statement. Where is %M% ? declare it first eg
#echo off
set M=""
for /f "tokens=1,2 delims=," %%x in (file) do (
if %M% LSS %%x set M=%%x
)
echo Max X Value= %M%
Alternative, you can use vbscript
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strFile = objArgs(0)
Set objFile = objFS.OpenTextFile(strFile)
t=0
Do Until objFile.AtEndOfStream
linenum = objFile.Line
strLine = objFile.ReadLine
s = Split(strLine,",")
For Each num In s
WScript.Echo "num "&num
If Int(num) >= t Then
t=Int(num)
End If
Next
WScript.Echo "Max for line:" & linenum & " is " & t
Loop
example output
C:\test>type file
422,34464,55455,65421,88
C:\test>cscript //nologo test.vbs file
Max for line:1 is 65421
UPDATE: To find max value column wise
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strFile = objArgs(0)
Set objFile = objFS.OpenTextFile(strFile)
t=0
Do Until objFile.AtEndOfStream
linenum = objFile.Line
strLine = objFile.ReadLine
s = Split(strLine,",")
If Int(s(0)) >= t then
t=Int(s(0))
End If
Loop
WScript.Echo "Max is " & t & " (line: " & linenum & ")"
output
C:\test>type file
422,34
464,55
455,65
421,88
C:\test>cscript //nologo test.vbs file
Max is 464 (line: 2)

Resources