Windows batch script to download yesterday files - windows

I am writing a script using ftp.exe to download files from an FTP server, it works at first. But the version I wrote was suited for only one file and the current date. My script is below:
echo user>>ftp.txt
echo password>>ftp.txt
set prefix=%date:~0,10%
set "name=%prefix%.txt"
echo get %name% >> ftp.txt
echo bye >> ftp.txt
ftp -s:ftp.txt ftpserver.com
del ftp.txt
But now there are more than one file named like aa-bb-2011-09-13.0.log,
aa-bb-2011-09-13.1.log,
aa-bb-2011-09-13.10.log. The last number is a serial number, it could be 0, 1, 2, 3...
How could download these files by batch script? How to modify my script to download more than one file (the number is unknown) which file name pattern is yesterday?

In terms of downloading multiple files, use mget instead of get. The former allows you to specify wildcards for getting rather than specific files.
You'll just have to construct the "name" with a wildcard pattern, and make sure you have a prompt in your script before mget otherwise it will ask for confirmation on every file.
This is untested, but it's probably as simple as changing:
echo get %name% >> ftp.txt
to something like:
echo prompt>>ftp.txt
echo mget *%prefix%*>>ftp.txt
In terms of getting yesterdays date, you can use the following script. It's pretty complex compared to what you would do in, for example bash, but it works.
#setlocal enableextensions enabledelayedexpansion
#echo off
rem Get the date from WMI (on one line).
for /f "skip=2 tokens=2-7 delims=," %%A in ('wmic
path win32_localtime get day^,month^,year^ /format:csv') do (
set /a "yest_yyyy = %%C"
set /a "yest_mm = %%B"
set /a "yest_dd = %%A"
)
rem Not the first of the month, just decrement day.
if not %yest_dd%==1 (
set /a yest_dd = yest_dd - 1
goto done
)
rem Jan 1, set to Dec 31 previous year.
if %yest_mm%==1 (
set /a "yest_dd = 31"
set /a "yest_mm = 12"
set /a "yest_yyyy = yest_yyyy - 1"
goto :done
)
rem Any other day, decrement month.
set /a "yest_mm = yest_mm - 1"
rem Need to find last day, default to 31.
set dim=31
rem Apr/Jun/Sep/Nov all have 30 days. Feb gets special handling.
if %yest_mm%==4 set dim=30
if %yest_mm%==6 set dim=30
if %yest_mm%==9 set dim=30
if %yest_mm%==11 set dim=30
if not %yest_mm%==2 goto :got_dim
rem Default Feb to 28 then use rules to override.
set dim=28
set /a "divid=yest_yyyy%%400"
if "%divid%"=="0" goto daysinmonth_29days
set /a "divid=yest_yyyy%%100"
if "%divid%"=="0" goto :done
set /a "divid=yest_yyyy%%4"
if not "%divid%"=="0" goto :done
rem Adjust to 29 days.
:daysinmonth_29days
set dim=29
:done
rem Pad out and return value.
if %yest_mm% lss 10 set yest_mm=0%yest_mm%
if %yest_dd% lss 10 set yest_dd=0%yest_dd%
set yesterday=%yest_yyyy%-%yest_mm%-%yest_dd%
endlocal && set yesterday=%yesterday%
It will set the yesterday environment variable to the format YYYY-MM-DD so that you can use it in your current script. Simply invoke call yesterday.cmd and then use the environment variable.

It's a pretty complex task to implement with Windows batch-file and the built-in FTP client (ftp.exe).
It would be more easier with PowerShell.
And even easier using a more capable FTP client, like the latest version of WinSCP FTP client.
If you want to download files based on a pattern in a file name, this will do:
winscp.com /ini=nul /log=yesterday.log /command ^
"open ftp://username:password#ftp.example.com/" ^
"get /remote/path/*%%TIMESTAMP-1D#yyyy-mm-dd%%* C:\local\path\" ^
"exit"
This uses the %TIMESTAMP% syntax
If you want to download based on a file modification time, use a file mask with a time-constraint:
winscp.com /ini=nul /log=yesterday.log /command ^
"open ftp://username:password#ftp.example.com/" ^
"get /remote/path/*>=yesterday<today C:\local\path\" ^
"exit"
The >=yesterday<today syntax is supported by WinSCP 5.15 and newer.
In older versions of WinSCP, you can again use %TIMESTAMP% syntax, particularly >=%%TIMESTAMP-1D#yyyy-mm-dd%%<%%TIMESTAMP#yyyy-mm-dd%%, instead of >=yesterday<today.
(I'm the author of WinSCP)

This is a sample FTP script that does almost exactly what you need but it uses a 3rd party client instead of the one that comes free with Windows: http://kb.robo-ftp.com/script_library/show/45
Maybe you can convert it.

Related

download file from FTP and store those files in daily dated folder [duplicate]

I am writing a script using ftp.exe to download files from an FTP server, it works at first. But the version I wrote was suited for only one file and the current date. My script is below:
echo user>>ftp.txt
echo password>>ftp.txt
set prefix=%date:~0,10%
set "name=%prefix%.txt"
echo get %name% >> ftp.txt
echo bye >> ftp.txt
ftp -s:ftp.txt ftpserver.com
del ftp.txt
But now there are more than one file named like aa-bb-2011-09-13.0.log,
aa-bb-2011-09-13.1.log,
aa-bb-2011-09-13.10.log. The last number is a serial number, it could be 0, 1, 2, 3...
How could download these files by batch script? How to modify my script to download more than one file (the number is unknown) which file name pattern is yesterday?
In terms of downloading multiple files, use mget instead of get. The former allows you to specify wildcards for getting rather than specific files.
You'll just have to construct the "name" with a wildcard pattern, and make sure you have a prompt in your script before mget otherwise it will ask for confirmation on every file.
This is untested, but it's probably as simple as changing:
echo get %name% >> ftp.txt
to something like:
echo prompt>>ftp.txt
echo mget *%prefix%*>>ftp.txt
In terms of getting yesterdays date, you can use the following script. It's pretty complex compared to what you would do in, for example bash, but it works.
#setlocal enableextensions enabledelayedexpansion
#echo off
rem Get the date from WMI (on one line).
for /f "skip=2 tokens=2-7 delims=," %%A in ('wmic
path win32_localtime get day^,month^,year^ /format:csv') do (
set /a "yest_yyyy = %%C"
set /a "yest_mm = %%B"
set /a "yest_dd = %%A"
)
rem Not the first of the month, just decrement day.
if not %yest_dd%==1 (
set /a yest_dd = yest_dd - 1
goto done
)
rem Jan 1, set to Dec 31 previous year.
if %yest_mm%==1 (
set /a "yest_dd = 31"
set /a "yest_mm = 12"
set /a "yest_yyyy = yest_yyyy - 1"
goto :done
)
rem Any other day, decrement month.
set /a "yest_mm = yest_mm - 1"
rem Need to find last day, default to 31.
set dim=31
rem Apr/Jun/Sep/Nov all have 30 days. Feb gets special handling.
if %yest_mm%==4 set dim=30
if %yest_mm%==6 set dim=30
if %yest_mm%==9 set dim=30
if %yest_mm%==11 set dim=30
if not %yest_mm%==2 goto :got_dim
rem Default Feb to 28 then use rules to override.
set dim=28
set /a "divid=yest_yyyy%%400"
if "%divid%"=="0" goto daysinmonth_29days
set /a "divid=yest_yyyy%%100"
if "%divid%"=="0" goto :done
set /a "divid=yest_yyyy%%4"
if not "%divid%"=="0" goto :done
rem Adjust to 29 days.
:daysinmonth_29days
set dim=29
:done
rem Pad out and return value.
if %yest_mm% lss 10 set yest_mm=0%yest_mm%
if %yest_dd% lss 10 set yest_dd=0%yest_dd%
set yesterday=%yest_yyyy%-%yest_mm%-%yest_dd%
endlocal && set yesterday=%yesterday%
It will set the yesterday environment variable to the format YYYY-MM-DD so that you can use it in your current script. Simply invoke call yesterday.cmd and then use the environment variable.
It's a pretty complex task to implement with Windows batch-file and the built-in FTP client (ftp.exe).
It would be more easier with PowerShell.
And even easier using a more capable FTP client, like the latest version of WinSCP FTP client.
If you want to download files based on a pattern in a file name, this will do:
winscp.com /ini=nul /log=yesterday.log /command ^
"open ftp://username:password#ftp.example.com/" ^
"get /remote/path/*%%TIMESTAMP-1D#yyyy-mm-dd%%* C:\local\path\" ^
"exit"
This uses the %TIMESTAMP% syntax
If you want to download based on a file modification time, use a file mask with a time-constraint:
winscp.com /ini=nul /log=yesterday.log /command ^
"open ftp://username:password#ftp.example.com/" ^
"get /remote/path/*>=yesterday<today C:\local\path\" ^
"exit"
The >=yesterday<today syntax is supported by WinSCP 5.15 and newer.
In older versions of WinSCP, you can again use %TIMESTAMP% syntax, particularly >=%%TIMESTAMP-1D#yyyy-mm-dd%%<%%TIMESTAMP#yyyy-mm-dd%%, instead of >=yesterday<today.
(I'm the author of WinSCP)
This is a sample FTP script that does almost exactly what you need but it uses a 3rd party client instead of the one that comes free with Windows: http://kb.robo-ftp.com/script_library/show/45
Maybe you can convert it.

How can I run redis lua scripts in windows

I came across this article on how to run lua scripts against redis. But this article is geared towards those running on *nix. How can I execute a redis lua script from a windows environment?
Read First:
After doing this and fighting with this script for nearly a week, I decided to try and use one of the java libraries to do the scripting instead. I've created a public repo with that project in it. The benefits are that you are not limited to a ~8000 character input variable and it runs much much faster. I'm going to leave the batch script here for people who absolutely need to do it this way, but I would highly recommend using the java code instead:
Redis Scripting Project
Actual Answer:
Using a batch file I was able to replicate the bash script from that article.
#echo off
setlocal EnableDelayedExpansion
echo Starting removal of keys from redis.
echo KeyMatch: %1
echo Field: %2
echo Script: %3
echo Host: %4
echo Port: %5
REM set the cursor to 0 to begin iterating over matching keys
set cursor=0
:loop
REM call redis scan and output the result to temp.txt
call redis-cli -h %4 -p %5 scan !cursor! match %1 count 180 > temp.txt
REM set the first line of the temp file to the new cursor variable
set /p cursor=<temp.txt
REM outer loop variables
set /A i=0
set keyString=
REM loop through the text file to build the key string
for /F "usebackq delims=" %%a in ("temp.txt") do (
set /A i+=1
REM if we are not on the first line save the key to a space delimted string
if NOT !i! == 1 (
call set keyString=!keyString! %%a
)
)
rem if there is only one line in the file skip the script execution
if !i! LEQ 1 (
goto :checkCursor
)
rem check that the length of keyString will not likely violate the 8192 character limit to command line calls
ECHO !keyString!> strlength.txt
FOR %%? IN (strlength.txt) DO ( SET /A strlength=%%~z? - 2 )
if !strlength! GTR 8000 (
echo.
echo.
echo ****Error processing script. Key string is too long. Reduce the count in call to scan.****
echo.
echo.
GOTO :end
)
REM call the script with the keys from the scan task, output to result.txt to prevent writing to the command line each iteration.
call redis-cli -h %4 -p %5 --eval %3 !keyString:~1! , %2 > result.txt
REM output '.' to the commandline to signify progress
<nul set /p=.
:checkCursor
if not !cursor!==0 (
goto :loop
)
:end
set fileToDelete=temp.txt
if exist !fileToDelete! del /F !fileToDelete!
set fileToDelete=result.txt
if exist !fileToDelete! del /F !fileToDelete!
set fileToDelete=strlength.txt
if exist !fileToDelete! del /F !fileToDelete!
echo Completed script execution
endlocal
you can call this script from the command line like:
batchScriptName keyMatch field luaScriptName.lua host port
batchScriptName myKey* us luaScriptName.lua localhost 6379
If your batch script is not on your path then you will have to call the command from the directory where your file is located. Also with the lua scripts you will need to give the full file path reference or call the batch script from the directory where the lua script is located.
This script is set up to work with hashed values in redis. If you need to alter that, you will likely want to change this line:
call redis-cli -h %4 -p %5 --eval %3 !keyString:~1! , %2 > result.txt
The '%2' passes in the field value to the ARGV array in the lua script and you can remove this if you do not need it. You can also add additional ARGV parameters as needed.

Batch Hex to Asciic makes the string useless?

I belive i found a nice way to send out a command line to multiple batch windows at once, here is how i see it going:
Using Set with /p allows me to user input a string that i save as message
Exporting it to its own bat file with "Echo set command=%message% >command.bat
Using echo to type out ftp information and then run it with "Ftp -s:upload.txt ftp.example.com
This uploads it to my webhotel where im gonna use a bitadmin.exe to download the file
Then running command.bat and ensuring that if the string %command% isnt the same before it runs the command
It's all working fine and what not, but i feel like my ftp name/password is too exposed to anyone that has the IQ to "Right-Click, Edit" and inspect the code. I've come to the point where i'm trying to make it harder to really get it just by looking at the batch file.
So far i converted my password into HEX and using a fancy batch file convert it back into a string from a batch file i call, and then export it with the ftp connection file. It works all up untill the batch reads the ftp connection file and gets stuck on "requiring password" even though when i check my ftp connection file then the password is correctly typed in the right place, no additional spaces or odd stuff. But it wont work untill i deleted the line and typed it in my self. (The other way that i was considering using a Batch to exe program but that just runs the batch file in the temp folder, everyone knows that) The hex password i use here is just "password"
Code so far:
#Echo Off
:Start
Rem (1)Set/(2)Export Message
Rem (1)
Set /p message=
Rem (2)
Echo set run=%message% >command.bat
Rem (1)Decode Hex/(2)Running hex output/(3)Acces FTP service
Rem (1)
Start HEX.bat 70617373776f7264
Rem (2)
Call CODE.bat
Del /Q CODE.bat
Rem (3)
Echo darkrock> upload.txt
Echo %code%>> upload.txt
Echo asc>>upload.txt
Echo put command.bat>> upload.txt
Echo quit >> upload.txt
Ftp -s:upload.txt ftp.example.com
Goto :Start
The hex converter comes here:
#echo off
setlocal DisableDelayedExpansion
set Caret=^^
set ControlChar={SOH} {STX} {ETX} {EOT} {ENQ} {ACK} {BEL} {BS} {HT} {LF} {VT} {FF} {CR} {SO} {SI} {DLE} {XON}
set ControlChar=%ControlChar% {DC2} {XOFF} {DC4} {NAK} {SYN} {ETB} {CAN} {EM} {SUB} {ESC} {FS} {GS} {RS} {US}
set AsciiChar= !"#$%%&'()*+,-./0123456789:;<=>?
setlocal EnableDelayedExpansion
set AsciiChar=!AsciiChar!#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]!Caret!_`abcdefghijklmnopqrstuvwxyz{^|}~
set AsciiChar=!AsciiChar!€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿
set AsciiChar=!AsciiChar!ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
set HexCode=%1
call :Conversion
echo Hex: %1
echo Dec: %DecimalCode%
echo Ascii: !AsciiCode!
echo Bin: %BinaryCode%
cls
goto :EOF
:Conversion
set DecimalCode=
set AsciiCode=
set BinaryCode=
:ConvertHex
set /A Decimal=0x%HexCode:~0,2%, DecChar=Decimal-32
set DecimalCode=%DecimalCode%%Decimal%,
if %Decimal% lss 32 (
if %Decimal% equ 0 (
set AsciiCode=!AsciiCode!{NUL}
) else (
for /F "tokens=%Decimal%" %%c in ("%ControlChar%") do set AsciiCode=!AsciiCode!%%c
)
) else (
set AsciiCode=!AsciiCode!!AsciiChar:~%DecChar%,1!
)
call :DecToBin
set BinaryCode=%BinaryCode%%Binary%,
set HexCode=%HexCode:~2%
if defined HexCode goto ConvertHex
exit /B
:DecToBin
set Binary=
for /L %%i in (1,1,8) do (
set /A "Bit=Decimal&1, Decimal>>=1"
set Binary=!Bit!!Binary!
)
echo set code=%AsciiCode% >Code.bat
exit /B
Thx in advance! :) It might be me that missed something in the code but i belive i tried by best the last two days compared to being busy with collage.

Batch file setting variable in if/else statement in For Loop

I'm trying to create a batch file that generates a custom AVIsynth script per each file. Right now the batch file is set to execute from within the folder where the video files exist. What I need to do is get the creation time of the file to generate a timecode burn in. I have no problem getting the info I need. However, if the file was created in the afternoon I need it to be in 24hr time. For example, 2pm needs to display as 14.
I have a working if statement that creates a newth variable that adds 12 if need be. However, if it doesn't need it the variable persists. On each subsequent iteration of the loop the variable doesn't change.
My example. I have two files the first was created at 2pm the other at 12pm. The 2pm file is read first and the newth variable becomes 14. So far so good. On the next file the newth variable should become 12 but instead remains 14. How do I fix this?
#Echo Off & CLS
SetLocal EnableDelayedExpansion
For /F %%a In ('dir *.mpg /b') Do (
ECHO Processing "%%a"
echo %%~ta
set time=%%~ta
set th=!time:~11,2!
set tm=!time:~14,2!
set era=!time:~17,2!
echo !era!
if "!era!"=="PM" (
if !th! LSS 12 ( set /a newth=!th!+12 )
) else ( set /a newth=!th!)
echo !newth!
echo //AviSynth Test Script >scripts/%%a.avs
echo DirectshowSource^("%%~fa"^)>>scripts/%%a.avs
echo LanczosResize^(720,400^) >>scripts/%%a.avs
echo ShowSMPTE^(^) >>scripts/%%a.avs
ECHO Back to Console
Pause
)
It's a little messy because I've been using echo for debugging. But hopefully the problem is clear.
Here is a method with Wmic - Wmic is in XP pro and above.
#Echo Off & CLS
SetLocal EnableDelayedExpansion
For /F "delims=" %%a In ('dir *.mpg /b') Do (
ECHO Processing "%%a"
set "file=%cd%\%%a"
set "file=!file:\=\\!"
WMIC DATAFILE WHERE name="!file!" get creationdate|find ".">file.tmp
for /f %%a in (file.tmp) do set dt=%%a
set tm=!dt:~8,2!:!dt:~10,2!:!dt:~12,2!
del file.tmp
echo !tm!
echo //AviSynth Test Script >scripts/%%a.avs
echo DirectshowSource^("%%~fa"^)>>scripts/%%a.avs
echo LanczosResize^(720,400^) >>scripts/%%a.avs
echo ShowSMPTE^(^) >>scripts/%%a.avs
ECHO Back to Console
Pause
)
There are a few problems with your code. The major one is this sequence
if "!era!"=="PM" (
if !th! LSS 12 ( set /a newth=!th!+12 )
) else ( set /a newth=!th!)
With your first filetime "02:xx PM"
th=02, era=PM, so set /a newth=02+12 sets newth=14
With your second filetime "12:xx PM"
th=12, era=PM, so - do nothing, since there's no else action for !th! LSS 12
Hence, newth remains at 14.
So - what's the fix? Since you don't use newth further, we can't say for certain, but it appears you want 24-hour format - 4 digit hhmm.
DANGER, Will Robinson moment number 1:
You are dealing with numbers starring LEADING ZEROES. All well and good except where the value is 08 or 09, which batch bizarrely interprets as OCTAL since it begins 0.
DANGER, Will Robinson moment number 2:
set /a will suppress leading zeroes, so set /a newth=!th! will set newth to 7 for time 07:36 AM - not 07...
So - how to overcome all this?
IF !th!==12 SET th=00
SET th=!th: =0!
if "!era!"=="PM" (set /a newth=1!th!+12
SET newth=!newth:~-2!
) else ( set newth=!th!)
This forces 12 AM to 00 AM and 12 PM to 00 PM
Then replace any spaces with 0 (in case you have leading spaces, not zeroes)
Then, if era is PM, add 100 by stringing 1 before the 2-digit hour number, add 12 and grab the last 2 characters
Otherwise, just use the number in th
Unfortunately, made a little more complicated since you haven't told us whether you use or don't use leading zeroes in your time format. Nevertheless, the incomplete original calculation method is at fault.
DANGER, Will Robinson moment number 3:
time is a MAGIC VARIABLE - and you know what happened to Mickey when he got involved in things better left alone.
If you set time in a batch, then %time% or !time! will return the value you set. If you don't set it, then the value returned will be the system time. Same goes for DATE and a number of similar values (see set /? from the prompt - there's a list at the end)
here's how you can get the time stamp with seconds:
C:\>powershell -command "& {(gwmi -query """select * from cim_datafile where name = 'C:\\file.txt' """).lastModified;}"
C:\>powershell -command "& {(gwmi -query """select * from cim_datafile where name = 'D:\\other.txt' """).creationdate;}"
I've tried with WMIC but still cannot get the time stamp.As you are using Win7 you should have powershell installed by default.

Windows batch file - check if file has been modified

I'm configuring a windows machine to continuously run a powerpoint presentation. The ppt file is located on a samba share (windows file sharing) and will be updated periodically. I need a way to make a batch file that will restart the ppt slide show if the file has been changed. The batch script will run on a a regular interval, and will hopefully check to see if the file has been updated, and re-start the slideshow if it has.
If there is a way to do this in powershell, that would work too.
Well, in a batch, the easiest way I would think of would be to periodically check whether the file's last modification date and/or its size has changed.
You can get both via the following:
for %%X in (myfile) do set size=%%~zX&set filetime=%%~tX
You can then cache those values and compare whether they have changed since the last iteration. Using a delay (a few seconds maybe) via
ping -n 11 localhost >nul 2>nul
(for 10 seconds delay) can help in not checking too often.
So, it might look a little like the following:
#echo off
setlocal
set FileName=MyPresentation.pptx
set FileTime=-
:loop
for %%X in (%FileName%) do (
if %FileTime% NEQ %%~tX (
rem just an example
taskkill /f powerpnt.exe
start %FileName%
)
set FileTime=%%~tX
)
rem wait 5 seconds before checking again
ping -n 6 localhost >nul 2>nul
goto :loop
In PowerShell the code wouldn't look too different, except that you get to the relevant properties a little easier:
$FileName = "MyPresentation.pptx"
$FileTime = Get-Date
# endless loop
for () {
$file = Get-Item $FileName
if ($FileTime -ne $file.LastWriteTime) {
Get-Process powerpnt* | Stop-Process
Invoke-Item $file
}
$FileTime = $file.LastWriteTime
Start-Sleep 5
}
Try the code below. It checks for the current time and checks when the file was last modified. If the two values are the same it is assumed the file was altered.
#echo off &setlocal
TITLE File Monitor
Set file=Test.txt
:CheckforAlter
Set modif_time=
Set allm=
cls
for /f "tokens=1-3 delims=:,. " %%A in ("%time%") do (
set "Hour=%%A"
set "Min=%%B"
set "Sec=%%C"
)
set /a Hour = Hour %% 12
if %Hour%==0 set "Hour=12"
set "Allm=%Hour%:%Min%:%Sec%"
for /f %%i in ('"forfiles /m %file% /c "cmd /c echo #ftime" "') do set modif_time=%%i
echo.
echo.
IF %modif_time%==%Allm% (
echo File was altered.
start "" "%file%"
Timeout /t 1 >nul
)
echo file wasn't modified.
GOTO CheckforAlter
Found this:
#echo off
if not "%~1"=="" echo Modified date of %~1 is %~t1
on Experts exchange. Maybe a good point to start from.

Resources