I wrote a batch that check days and time to execute particular actions.
For the time I use this:
for /f "tokens=1-3 delims=:" %%a in ("%time%") do if %%a geq 7 if %%a leq 18 goto email
And it works pretty good.
Now I would like to ensure we execute actions only from Monday to Friday.
I think with this sentence I can have a number by day (1 = Monday and so on...):
wmic path win32_localtime get dayofweek
Someone could help me to combine them to check time and day and do action or not?
Thanks for your help.
Regards
As shown here, you could write:
#echo off
set daysofweek=Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
for /F "skip=2 tokens=2-4 delims=," %%A in ('WMIC Path Win32_LocalTime Get DayOfWeek /Format:csv') do set daynumber=%%A
for /F "tokens=%daynumber% delims=," %%B in ("%daysofweek%") do set day=%%B
echo day number %daynumber%
echo day %day%
(script copied from http://www.sysnative.com/forums/windows-tips-tricks)
Related
I am learning to code the BATCH,
I would like to make a small .bat executable to retrieve various information on computers that I reinstall, to avoid having to navigate through several sections of the windows control panel.
I have already managed to retrieve some information using "for /f", but I must admit that I still don't understand how this command works.
I haven't found any more info on what I'm looking for, so I'm asking for help which would be very welcome.
I'm not looking for a copy/paste solution, I'd like someone to explain my mistake and help me solve it so I can better understand where I went wrong.
Anyway, after reading this indigestible pamphlet, here are the commands I'm looking to run:
for /f "tokens=2 delims==" %%I in (
'wmic LOGICALDISK where DriveType!=4 get DeviceID /value'
) do for /f "delims=" %%# in ("%%I") do set "deviceid=%%~#"
for /f "tokens=2 delims==" %%I in (
'wmic LOGICALDISK where drivetype!=4 get description /value'
) do for /f "delims=" %%# in ("%%I") do set "description=%%~#"
for /f "tokens=2 delims==" %%I in (
'wmic LOGICALDISK where drivetype!=4 get volumename /value'
) do for /f "delims=" %%# in ("%%I") do set "volumename=%%~#"
for /f "tokens=2 delims==" %%I in (
'wmic LOGICALDISK where drivetype!=4 get Size /value'
) do for /f "delims=" %%# in ("%%I") do set "Size=%%~#"
and this is what I get back:
C:\Users\rv\Desktop>for /F "tokens=2 delims==" %I in ('wmic LOGICALDISK where DriveType! 4 get DeviceID /value') do for /F "delims=" %# in ("%I") do set "deviceid=%~#"
4 - Verbe de l'alias non valide.
C:\Users\rv\Desktop>for /F "tokens=2 delims==" %I in ('wmic LOGICALDISK where drivetype! 4 get description /value') do for /F "delims=" %# in ("%I") do set "description=%~#"
4 - Verbe de l'alias non valide.
C:\Users\rv\Desktop>for /F "tokens=2 delims==" %I in ('wmic LOGICALDISK where drivetype! 4 get volumename /value') do for /F "delims=" %# in ("%I") do set "volumename=%~#"
4 - Verbe de l'alias non valide.
C:\Users\rv\Desktop>for /F "tokens=2 delims==" %I in ('wmic LOGICALDISK where drivetype! 4 get Size /value') do for /F "delims=" %# in ("%I") do set "Size=%~#"
4 - Verbe de l'alias non valide.
I think this is due to a misuse of "tokens=" and "delims=" on my part ?
Mmm... I used to think/solve this type of problems in "opposite order"... Please, follow me.
I started typing this command at the command-prompt:
C:\> wmic LOGICALDISK where DriveType!=4 get DeviceID /value
DeviceID=C:
DeviceID=D:
Ok. I always try to make things in an efficient way. If I can get the same result from a single command instead of 4 commands, then I always opted for the single one:
C:\> wmic LOGICALDISK where DriveType!=4 get DeviceID,Description,VolumeName,Size /value
Description=Local Fixed Disk
DeviceID=C:
Size=982768414720
VolumeName=Windows
Description=Local Fixed Disk
DeviceID=D:
Size=16111366144
VolumeName=RECOVERY
Good! In order to "get" such values, we need to execute the wmic command from a for /F command, so I wrote this simple Batch file at first:
for /F "delims=" %%a in ('wmic LOGICALDISK where DriveType!=4 get DeviceID,Description,VolumeName,Size /value') do #echo [%%a]
... and the problems started:
C:\> for /F "delims=" %a in ('wmic LOGICALDISK where DriveType! 4 get DeviceID Description VolumeName Size /value') do #echo [%a]
4 - Verbo de alias no válido.
If you compare the source line vs. the executed command, you'll realize that the equal-sign and the commas disappeared! This happens because these characters: = , ; works as separators for items in most commands (besides space and TAB). This is this way just because MS (Microsoft) decided that... :(
There are two ways to solve this problem: individually caret-^escape each one of these characters OR enclose the whole command in quotes. I choose the second method because it is simpler:
for /F "delims=" %%a in ('"wmic LOGICALDISK where DriveType!=4 get DeviceID,Description,VolumeName,Size /value"') do #echo [%%a]
And the output is:
C:\> for /F "delims=" %a in ('"wmic LOGICALDISK where DriveType!=4 get DeviceID,Description,VolumeName,Size /value"') do #echo [%a]
]
]
]Description=Local Fixed Disk
]DeviceID=C:
]Size=982768414720
]VolumeName=Windows
]
]
]Description=Local Fixed Disk
]DeviceID=D:
]Size=16111366144
]VolumeName=RECOVERY
]
]
]
So far so good, we have solved the equal-sign and comma problem... However, a new problem arises: the lines we think were empty really contain a CR character! There are a couple methods to solve this new point, and the one you used before is the simplest one: process the wmic output lines in a second FOR command:
for /F "delims=" %%a in (
'"wmic LOGICALDISK where DriveType!=4 get DeviceID,Description,VolumeName,Size /value"'
) do #(
for /F "delims=" %%b in ("%%a") do #echo [%%b]
)
And the output is:
C:\> for /F "delims=" %a in ('"wmic LOGICALDISK where DriveType!=4 get DeviceID,Description,VolumeName,Size /value"') do #(for /F "delims=" %b in ("%a") do #echo [%b]
)
[Description=Local Fixed Disk]
[DeviceID=C:]
[Size=982768414720]
[VolumeName=Windows]
[Description=Local Fixed Disk]
[DeviceID=D:]
[Size=16111366144]
[VolumeName=RECOVERY]
Perfect! Now, that we are sure that the code will process the values we want, we insert an #echo off command at beginning and split each line in two parts, the variable and its value:
#echo off
for /F "delims=" %%a in (
'"wmic LOGICALDISK where DriveType!=4 get DeviceID,Description,VolumeName,Size /value"'
) do (
for /F "tokens=1,2 delims==" %%b in ("%%a") do echo [%%b=%%c]
)
The output is the same than before.
Finally, we insert code to save the value of each variable and process all variables each time that a group is complete; that is:
#echo off
setlocal EnableDelayedExpansion
set "VolumeName="
for /F "delims=" %%a in (
'"wmic LOGICALDISK where DriveType^!=4 get DeviceID,Description,VolumeName,Size /value"'
) do (
for /F "tokens=1,2 delims==" %%b in ("%%a") do set "%%b=%%c"
if defined VolumeName (
echo/
echo ===== New disk =====
echo Description=!Description!
echo DeviceID=!DeviceID!
echo Size=!Size!
echo VolumeName=!VolumeName!
set "VolumeName="
)
)
The final output:
===== New disk =====
Description=Local Fixed Disk
DeviceID=C:
Size=982768414720
VolumeName=Windows
===== New disk =====
Description=Local Fixed Disk
DeviceID=D:
Size=16111366144
VolumeName=RECOVERY
Note that in the last code the exclamation-mark needs to be ^escaped. This is because the EnableDelayedExpansion setlocal's option enables the ! as a method to expand variables additional to the %standard% one. You can find a lot of questions/answers about this topic in this site...
How-to: Escape Characters, Delimiters and Quotes at the Windows command line.
In Windows cmd/batch scripting, parameters are most often separated by spaces, but any of the following are also valid delimiters:
, (U+002C, Comma)
; (U+003B, Semicolon)
= (U+003D, Equals Sign)
(U+0020, Space)
␉ (U+0009, Character Tabulation)
You need to escape the Equals Sign in DriveType!=4. Use any of the following:
"DriveType!=4" (using "Double Quotes")
DriveType!^=4 (using common escape character ^ (U+005E, Circumflex Accent))
So, I have a script to log the date and time in a text file:
for /f "tokens=2 delims==" %%G in ('wmic os get localdatetime /value') do set datetime=%%G
set year=%datetime:~0,4%
rem pause
set month=%datetime:~4,2%
set day=%datetime:~6,2%
set /a day2=day+5
echo %year%/%month%/%day2%> C:\WLT\Init\lastoptim.txt
And a similar one in a script that runs on startup:
for /f "tokens=2 delims==" %%G in ('type C:\WLT\Init\lastoptim.txt') do set datetime2=%%G
set year=2%datetime2:~0,4%
rem pause
set month2=%datetime2:~4,2%
set day2=%datetime2:~6,2%
set /a day3=day2+1
echo %year2%/%month2%/%day3%> lastoptim2.txt
echo %year2%/%month2%/%day3%
But it doesn’t work. What I need is a script to extract a date from %date% into a text file, and then another one to take that date, see if the current date is X number of days later, and if it is, then run a command.
Would like this script to be entirely dependent on cmd, because this is going to be used on systems as far back as XP. Using an external app (e.g. an exe that prints out the date in a specific format) would be fine.
Your question still not clear for me, but if you want to add one day or one month for your dates, here is an example :
#echo off
Title Manipulate DATES WITH BATCH
#for /f "tokens=* delims=" %%a in ('wmic os get LocalDateTime /value') do for /f "tokens=* delims=" %%# in ("%%a") do set "%%#"
:: Store the local date inside a variable
set "CurrentDateTime=%LocalDateTime%"
set "CurrentDate=%CurrentDateTime:~0,4%/%CurrentDateTime:~4,2%/%CurrentDateTime:~6,2%"
:: Here Adding One day
#for /f %%a in ('Powershell -C "(Get-Date).AddDays(1).ToString('yyyy/MM/dd')"') do set "NextDay=%%a"
:: Here adding 1 month
#for /f %%a in ('Powershell -C "(Get-Date).AddMonths(1).ToString('yyyy/MM/dd')"') do set "NextMonth=%%a"
echo( CurrentDate : %CurrentDate%
echo( NextDay : %NextDay%
echo( NextMonth : %NextMonth%
pause
I thought this would be easy but I'm stuck. I have a batch file that will let me back up all 'Actual' (not system) user profiles which is fine & working good. However, an age limitation to the profile folders being backed up has to be applied. Only backing up all the user profiles folder with a last modified date of 60 days is allowed, rather just blind copying the whole lot (time & disk space etc.)
I thought adding the /MAXAGE switch to the robocopy line would suffice but seems even if the profile is recently active (within the date copy criteria) important files older than 60 days within the folder structures are left out - which is not good!
I had a look into Forfiles which seemed would be useable but doesn't deal with folder dates, just files (it seems?). Also the Dir /T:W switch but outputs syntax I can't blend into the current batch file.
Here is the code...
#echo off
pushd %~dp0
color 5F
for /F "Skip=1 Tokens=* Delims=\" %%G in (
'"WMIc Path Win32_UserProfile Where (Special!='True') Get LocalPath"'
) Do for /F "delims= " %%H in ("%%G") do (
for /F "Tokens=3,4 delims=\" %%I in ("%%H") do (
robocopy "%%H" "C:\IT\%%I" /XD AppData /XD "Application Data" /XD "Local Settings" /XD *Drive* /MAXAGE:60 /E /R:0 /XA:SH
)
)
)
pause
So my question is, how can I make it check the last modified date of a user profile folder & back it up (including subfolders/files that maybe older than 60 days) as long as the root user profile folder has modified attribute within the last 60 days, else older, dont back up.
Hope that makes sense, thanks for any info / tips anyone may advise.
C:\Users\Admin Last Mod 12/12/2020 (>backup)
C:\Users\Dez.Smith Last Mod 19/11/2020 (>backup)
c:\Users\Smiley.Pippet Last Mod 16/09/2020 (<dont backup)
etc....
New Code...
#echo off
color 5F
for /f "tokens=2 delims==;." %%a in ('"wmic path Win32_UserProfile where (Special!='True' and LastUseTime is not null) get LastUseTime,LocalPath /VALUE | find "LastUseTime""') Do (
for /f "tokens=2 delims==" %%b in ('"wmic path Win32_UserProfile where (Special!='True' and LastUseTime is not null) get LastUseTime,LocalPath /VALUE | find "LocalPath""') Do (
echo %%a
pause
if %%a GTR 20200109230000 echo %%b
)
)
)
pause
From the output of the command I get
LastUseTime=20201212194437.654000+000
LocalPath=C:\Users\Admin
I was thinking I can strip that into what I need. So have trimmed the date to just 20201212194437 & also just C:\Users\Admin.
If I set a number to 60 days or what ever 20200109230000 (%%a) (1st Sept 11:00pm 00 secs) I thought I could use the GTR switch against it to then robocopy %%b
but it doesn't echo back...Not sure whats happening as if I echo %%a & %%b they resolve the snippets I want...cheers
The following script might accomplish what you want (see the rem-comments in the code):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_TARGET=D:\Backup\Profiles" & rem // (destination directory of the backup)
set /A "_MAXAGE=60" & rem // (maximum age in days of user profile)
rem // Retrieve current date/time:
for /F "delims=" %%U in ('
wmic path Win32_OperatingSystem get LocalDateTime /VALUE
') do for /F "delims=" %%V in ("%%U") do set "%%V"
rem // Loop through non-special non-roaming user profiles:
for /F "delims=" %%U in ('
wmic path Win32_UserProfile where "Special=FALSE and RoamingConfigured=FALSE and LastUseTime is not null and LocalPath is not null" ^
get LastUseTime^,LocalPath /VALUE
') do for /F "tokens=1* delims==" %%V in ("%%U") do (
rem // Store current item, which can be the last usage date or the source path:
set "%%V=%%W" & set "Name=%%~nxW" & setlocal EnableDelayedExpansion
rem // Check what the current item is:
if "%%V"=="LastUseTime" (
endlocal
rem // Current item is last usage date, so get difference to current date:
call set /A "RelUseDate=(((%LocalDateTime:~,4%*12+%LocalDateTime:~4,2%)*36525+%LocalDateTime:~6,2%00)-((%%LastUseTime:~,4%%*12+%%LastUseTime:~4,2%%)*36525+%%LastUseTime:~6,2%%00))/100"
) else if !RelUseDate! leq %_MAXAGE% (
rem // Current item is source path, so copy when last usage data is not too long ago:
ECHO robocopy "!LocalPath!" "!_TARGET!\!Name!" *.* /PURGE /XD "AppData" /XJ
endlocal
) else endlocal
)
endlocal
exit /B
Im using this code on a windows batch script:
FOR /F "TOKENS=1* DELIMS= " %%A IN ('DATE/T') DO SET CDATE=%%B
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET mm=%%B
FOR /F "TOKENS=1,2 DELIMS=/ eol=/" %%A IN ('echo %CDATE%') DO SET dd=%%B
FOR /F "TOKENS=2,3 DELIMS=/ " %%A IN ('echo %CDATE%') DO SET yyyy=%%B
SET date=%dd%%mm%%yyyy%
echo New folder name %date%
but the folder name is just 07on
i need to be able to save the file as dd-mm-yy h:m:s
I'm really not sure what you're trying to accomplish, but you might want to look at something like this:
Running this today (from a command prompt)
C:\>date
The current date is: Thu 07/04/2013
Enter the new date: (mm-dd-yy)
C:\>SET Today=%Date:~10,4%-%Date:~4,2%-%Date:~7,2%
C:\>ECHO %Today%
Produces
2013-07-04
It works like this:
SET Today=%Date:~10,4%-%Date:~4,2%-%Date:~7,2%
^ ^ ^ ^ ^
| | | | |
Year | Dash Month Day
|
Number of chars
You can get the time values the same way, replacing the %Date% with %Time% and adjusting the offsets the way you need to get the format you want to get.
You might also find this similar answer I posted helpful if you want to separate the year, month, and day into separate values.
This is a robust method to get date and time rather than rely on the PC regional settings. Requires XP Pro and higher.
#echo off
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set dt=%%a
set datestamp=%dt:~0,8%
set timestamp=%dt:~8,6%
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%-%Sec%
echo stamp: "%stamp%"
echo datestamp: "%datestamp%"
echo timestamp: "%timestamp%"
pause
Its easy. Just enter echo %time% or echo %date% and it will tell you. Hope it helps!
I've been working on some code in a batch file that evaluates two file dates. If one date is greater than the other then it runs another bat file. What I want to do is format the two dates as YYYYMMDD so that I can use the GTR (greater than).
The code is below but and it works if I use == (equal) because it's evaluating the string. I only want to know if one file date is greater than the other file date.
I'm not asking for someone to amend the code below but if you can show me how to format the dates I would be very grateful.
set Fileone=File1.txt
set FileTwo=File2.txt
pushd "D:\Board\Broadcast\FA_Report8_A"
FOR %%f IN (%FileOne%) DO SET filedatetime=%%~tf
FOR %%f IN (%FileTwo%) DO SET filedatetime2=%%~tf
SET filedatetime2=%year%%month%%day%
IF %filedatetime:~0, 10% GTR %filedatetime2:~0, 10% (
echo FileOne Greater - run bat
timeout /t 20 /nobreak
goto Finish
) else (
echo FileOne not Greater - Finish
goto Finish
)
:Finish
echo finished
pause
It's not portable between machines with different date formats but the simplest way is to use a substring: %var:~STARTPOS,LENGTH%
set filedatetime=14/06/2012 12:26
set filedatetime=%filedatetime:~6,4%%filedatetime:~3,2%%filedatetime:~0,2%
echo "%filedatetime%"
"20120614"
You can separate a date in its parts with a FOR /F command:
set filedatetime=14/06/2012 12:26
for /F "tokens=1-3 delims=/ " %%a in ("%filedatetime%") do (
set filedatetime=%%c%%b%%a
)
This form prevents you to make a mistake in the position or size of each substring, and is very easy to change the order of the parts. For example, if your date is MM/DD/YYYY:
set filedatetime=%%c%%a%%b
Type FOR /? for further details.
The layout for date variable strings in the system can be assumed by settings from the user, by regional and/or language, so, date is not 100% predictable layout to work with.
Try using wmic OS Get localdatetime /value because the result is 100% predictable:
LocalDateTime=20190609123708.733000-180
SO, if you use in for loop, adding 2 delimiters like =., (equal and dot), you go getting this string output:
20190609123708.
The layout from this command is predictable and works independent of regional settings, user settings or system language, so, the command will always return:
set _date=20190609123708
rem :: %_date:~0,4%_%_date:~4,2%_%_date:~6,2%
rem :: year:2019 | month:06 | day:09
In bat file:
#echo off & for /f "tokens=2delims==." %%i in ('wmic OS Get localdatetime /value ^|findstr /r [0-9]')do set "_date=%%i" & echo/%_date:~0,4%%_date:~4,2%%_date:~6,2%
In command line:
for /f "tokens=2delims==." %i in ('wmic OS Get localdatetime /value ^|findstr /r [0-9]')do set "_data=%i" & mkdir %_date:~0,4%_%_date:~4,2%_%_date:~6,2%
This commands result ::
20190609
May I can also suggest:
wmic Path Win32_LocalTime Get Day,Month,Year
In looping for:
#echo off & setlocal enabledelayedexpansion & set "_do=wmic Path Win32_LocalTime Get Day^,Month^,Year"
for /f "tokens=1-3delims= " %%a in ('!_do!^|findstr /r [0-9]')do set "y=%%c" & set "d=0%%a" & set "m=0%%b"
echo/!y!!m:~-2!!d:~-2! >nul
Result:
Day Month Year
9 6 2019
%%a %%b %%c
The difference is no zero in number for month/day less equal 9, so, you can use this bat to put leading zero in this case:
#echo off & setlocal enabledelayedexpansion & set "_do=wmic Path Win32_LocalTime Get Day^,Month^,Year"
for /f "tokens=1-3delims= " %%a in ('!_do!^|findstr /r [0-9]')do set "y=%%c" & set "d=0%%a" & set "m=0%%b"
echo/!y!!m:~-2!!d:~-2!
Result in YearMonthDay:
20190609
Obs.: In PowerShell, the layout can be customized simple by:
ToString("yyyyMMdd")
The strings can be set with ToString.
Sample: yyyy-MM-dd, dd-MM-yyyy, MM-dd-yyyy, MM_dd_yyyy, yyyy_MM_dd, etc..
The Powershell command:
$(Get-Date).ToString("yyyyMMdd")
Result:
2010609
See more about date variable layout output in batch here:
Safe way to get current day month and year in batch
Parsing Dates in Batch Files & Regional Settings / Locale
Update - How applying the comments/observations above in your bat, so, if I understood your code in this question:
#echo off & setlocal enabledelayedexpansion
set "Fileone=File1.txt" & set "FileTwo=File2.txt"
set "_both=!FileOne!-!FileTwo!" & rem cd /d "D:\Board\Broadcast\FA_Report8_A"
set "_path_back=%__CD__%" & rem :: you can use this "%__CD__%" or pushd "D:\Board\Broadcast\FA_Report8_A"
for /f "tokens=2delims==." %%i in ('wmic OS Get localdatetime /value ^|findstr /r [0-9]')do set "_date=%%i"
set _now=!_date:~0,4!!_date:~4,2!!_date:~6,2! & for /f "tokens=1*delims=-" %%i in ('echo/!_both!')do (
call :compare "%%~fi" & call :compare "%%~fj" & if !_dt_file_2! gtr !_dt_file_2! (
echo/ FileOne Greater - run bat & timeout /t 20 /nobreak & goto :run_bat
) else (echo/ FileOne not Greater - Finish & goto Finish)
)
:compare
set "_file=" & set "_file=%~1"
for /f "tokens=1delims=. " %%d in ('wmic datafile where name^='!_file:\=\\!' get LastModified ^|findstr /v "LastModified"')do (
if "!_dt_file_1!./" == "./" (set _dt_file_2=%%d) else (set _dt_file_2=%%d)
) & exit /b
:run_bat
call the_bat_to_run.cmd
:Finish
echo/Finished
So sorry by my limited English...