Batch File Time - batch-file

How do I add the time to this batch file when I rename the file?
The results look like this but need time also: Daily Report_Wed 08222018.pdf
#echo off
Pushd c:\Temp
pdftk *.pdf cat output %fn%.pdf
ren %fn%.pdf %fn%.xxx
del *.pdf
ren %fn%.xxx "Daily Report".pdf
for /f "tokens=1-3 delims=/" %%a in ('echo %date%') do set today=%%a%%b%%c
for %%f in (*.pdf) do ren "%%f" "%%~nf_%today%%%~xf"
mkdir "Daily Reports for Review"
move *.pdf "Daily Reports for Review"

Here's something that could get you close to what you want (I modified your 1st for loop):
e:\Work\Dev\StackOverflow>echo Date: [%date%], Time: [%time%]
Date: [2018-08-22], Time: [22:51:36.23]
e:\Work\Dev\StackOverflow>for /f "tokens=1-6 delims=/-:., " %a in ('echo %date: =0%-%time: =0%') do (echo set now=%a%b%c%d%e%f)
e:\Work\Dev\StackOverflow>(echo set now=20180822225136 )
set now=20180822225136
Notes:
Since I am directly in cmd window, and you're in a batch file you have to double the percent sign (%) for parameters (%a -> %%a, %b -> %%b, ... like you already have in your snippet). For more details, check [SS64]: Double %% symbols why are they needed in a batch file?
As you probably noticed (most likely due to "Regional settings"), my date format differs than yours (that's why I added the hyphen (-) in the delims list; also the items ordering is reversed), so you might get slightly different behaviors on different computers (things will get even worse on non English locales, as #Stephan noticed), so it's not a reliable solution (I guess this is batch processing generic)

Here's an untested example for you which uses WMIC to retrieve non locale dependent date and time values:
#Echo Off
If Exist "C:\Temp\*.pdf" (CD /D "C:\Temp") Else Exit /B
Rem The values below can be modified according to your language or preferred day names
Set "WeekDays=Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
For /F %%A In ('WMIC Path Win32_LocalTime Get /Value^|FindStr "[0-9]$"') Do Set "%%A"
For /F "Tokens=1%DayOfWeek%" %%A In (". . . . . . . . . %WeekDays%") Do Set "DayName=%%A"
For %%A In (Day Hour Minute Month Second) Do Call Set "%%A=0%%%%A%%" & Call Set "%%A=%%%%A:~-2%%"
Rem Choose the output %FileName% you want from the following variables:
Rem %Year% e.g. 2018
Rem %Quarter% e.g. 3
Rem %Month% e.g. 08
Rem %WeekInMonth% e.g. 4
Rem %Day% e.g. 22
Rem %DayOfWeek% as an integer where Monday from %WeekDays% is 1 e.g. 3
Rem %DayName% as a string taken from %WeekDays% e.g. Wednesday
Rem %Hour% in 24 hr format e.g. 21
Rem %Minute% e.g. 57
Rem %Second% e.g. 53
Set "FileName=%DayName% %Month%%Day%%Year%%Hour%%Minute%%Second%"
Rem Choose the full or relative output directory name
Set "DirName=Daily Reports for Review"
If Not Exist "%DirName%\" MD "%DirName%"
PDFTK *.pdf cat output "%DirName%\%FileName%.pdf" && Del /Q *.pdf
You will need to include the full or relative path to PDFTK on the last line if it is not located in the current working directory, (C:\Temp), or in %PATH%. Other than that, you should only make modifications to values on lines beginning with Set.
Empty lines and those Remarked can be optionally removed once you've made your modifications.

Related

Batch Recursive For Loop and non-ASCII characters in Folder Namers

This is my continuing attempt to build a filename format verification batch routine (batch variable exclamation points used in dir | findstr)
Here's where I'm at:
echo off
REM Ensure filenames are of the format ALBUM - TITLE
chcp 1254>nul
setlocal DisableDelayedExpansion
set /p CUTOFFDATE=Enter the Date of the Last Cleanup (yyyymmdd):
for /r "\\kodi-pc\g\itunes\iTunes Media\Podcasts\American Civil War\" %%i in (*.mp3) do (
set "FILENAME=%%~nxi"
set "FILEDATE=%%~ti"
call set "TITLE=%%FILENAME:* - = - %%"
call:SETALBUM
call set "FILEDATE=%%FILEDATE:~6,4%%%%FILEDATE:~0,2%%%%FILEDATE:~3,2%%"
setlocal EnableDelayedExpansion
if !FILEDATE! GTR !CUTOFFDATE! (
echo ~ALBUM~TITLE~FILENAME~ ~!ALBUM!~!TITLE!~!FILENAME!
)
endlocal
)
pause
exit /b
:SETALBUM
call set "ALBUM=%%FILENAME:%TITLE%=%%"
exit /b
Works great except where folder names contain non-ASCII characters (», ’, etc.). My effort has been to recognize bangs (!) but that accomplished I now have these other problems.
The foldername 'American Civil War' is merely a sample placeholder for this forum. In reality I loop through many hundreds of foldernames.
Thx.

Batch to check file size before proceed to printing

This batch currently im using to print our daily report from a website then saved it as pdf (as a backup) and print one hard copy.
During saving the pdf, there will be 2 different size of pdf files generated daily(1 day 1 pdf only). Size of some pdf will be more than 20kb which contain our daily report and some will be around 9kb (8485bytes) (empty report because that day no sales).
My target now to save paper by preventing those empty report will not be print on that day. So how to add some code into my current code so that before printing, batch will check for file size before go to printing job. If possible, I want to create a msgbox too so that user will be prompt when no pdf will be print because of report empty.
Refer to code below:
Setting date parameter
Creating folder and subfolders
Using wkhtmltopdf to webpage to PDF
Check file size before printing
This is what I want to add. If generated pdf size more that 9kb, proceed to No 5 and No 6 automatically. Else, prompt user using msgbox "No report for today, Press OK to shutdown computer"
Printing
Shutting down computer
#echo off
title Daily Report to PDF
REM ---------------------------------------------------------------------------
REM 1. Setting date parameter
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set date=%%a
set month=%date:~4,2%
if %month%==01 set monthname=January
if %month%==02 set monthname=Febuary
if %month%==03 set monthname=March
if %month%==04 set monthname=April
if %month%==05 set monthname=May
if %month%==06 set monthname=June
if %month%==07 set monthname=July
if %month%==08 set monthname=August
if %month%==09 set monthname=September
if %month%==10 set monthname=October
if %month%==11 set monthname=November
if %month%==12 set monthname=December
for /f %%i in ('wmic path win32_localtime get dayofweek ^| findstr [0-9]') do set dayofweek=%%i
if %dayofweek%==1 set dow=(Mon)
if %dayofweek%==2 set dow=(Tue)
if %dayofweek%==3 set dow=(Wed)
if %dayofweek%==4 set dow=(Thu)
if %dayofweek%==5 set dow=(Fri)
if %dayofweek%==6 set dow=(Sat)
if %dayofweek%==7 set dow=(Sun)
REM ---------------------------------------------------------------------------
REM 2. Creating folder and subfolders
set dir1="%USERPROFILE%\Desktop\TEST"
set day=%date:~6,2%
set months=%monthname:~0,3%
set year=%date:~0,4%
set fulldate=%day%%months%%year%%dow%
md %dir1%\"YEAR %year%"\%monthname% 2>NUL
cd %dir1%\"YEAR %year%"\%monthname%\
md a b c 2>NUL
REM ---------------------------------------------------------------------------
REM 3. Using wkhtmltopdf to webpage to PDF
set dir2="%USERPROFILE%\Desktop\TEST\YEAR %year%\%monthname%"
echo.
echo Saving report as %fulldate%.pdf
wkhtmltopdf -q -g https://www.google.com %dir2%\c\%fulldate%.pdf
echo.
REM ---------------------------------------------------------------------------
REM 4. Check file size before printing
REM ---------------------------------------------------------------------------
REM 5. Printing
echo Printing %fulldate%.pdf
echo.
echo "C:\\Program Files (x86)\Foxit Software\Foxit Reader\Foxit Reader.exe" /t %dir2%\c\%fulldate%.pdf
REM ---------------------------------------------------------------------------
REM 6. Shutting down computer
shutdown -s -t 60 -c
PAUSE
::EXIT
Here's an example batch-file which tries to mimic your posted example and which includes some changes, predominantly the Setting of date variables.
#Echo Off
Title Daily Report to PDF
Rem ------------------------------------------------------------------------
Rem 1. Setting date variables
Set "_WeekDays=Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
For /F %%A In ('WMIC Path Win32_LocalTime Get /Value^
^|FindStr "[0-9]$"')Do Set "_%%A"
For /F "Tokens=1%_DayOfWeek%" %%A In (". . . . . . . . . %_WeekDays%"
)Do Set "_DayFullName=%%A"
Set "_DayShortName=%_DayFullName:~,3%"
For %%A In (Day Hour Minute Month Second
)Do Call Set "_%%A=0%%_%%A%%" & Call Set "_%%A=%%_%%A:~-2%%"
For %%A In (January.01 February.02 March.03 April.04 May.05 June.06
July.07 August.08 September.09 October.10 November.11 December.12
)Do If ".%_Month%"=="%%~xA" Set "_MonthFullName=%%~nA"
Set "_MonthShortName=%_MonthFullName:~,3%"
Set "_FullDateString=%_Day%%_MonthShortName%%_Year%%_DayShortName%"
Rem ------------------------------------------------------------------------
Rem 2. Creating folder and subfolders
Set "_Dir1=%UserProfile%\Desktop\TEST\YEAR %_Year%\%_MonthFullName%"
For %%A In (a b c)Do MD "%_Dir1%\%%A" 2>NUL
Rem ------------------------------------------------------------------------
Rem 3. Using wkhtmltopdf to convert webpage to PDF
Echo=
Echo Saving report as %_FullDateString%.pdf
wkhtmltopdf -q -g https://www.google.com "%_Dir1%\c\%_FullDateString%.pdf"
Echo=
Rem ------------------------------------------------------------------------
Rem 4. Printing files with sizes over 8485 bytes
Set "_Exe1=%ProgramFiles(x86)%\Foxit Software\Foxit Reader\Foxit Reader.exe"
For %%A In ("%_Dir1%\c\%_FullDateString%.pdf")Do If %%~zA GTR 8485 (
Echo Printing %%A&Echo=&"%_Exe1%" /t "%_Dir1%\c\%_FullDateString%.pdf")
Rem ------------------------------------------------------------------------
Rem 5. Shutting down computer
ShutDown /S /T 60
Note: This script assumes that the executable wkhtmltopdf is able to run from the current directory at the time the batch script is run.

Rename all folders with owner name script

Im trying to change the name of folders inside a folder to the name of the folders owner..
Exemple, I have a folder with one hundred other folder's all with the name "My Documents" and all of the with a diferente owner.
I already find a way to find the name with the code:
dir /q
but I have no ideia on how to put it in a variable and use that variable to change the folders name...
The usual way to get a commands output is a for.
#echo off
for /f "skip=2 tokens=4,*" %%a in ('dir /q /ad^|find "<DIR>"') do (
for /f "tokens=2 delims=\" %%i in ("%%a") do (
echo owner=%%i
echo folder=%%b
echo ren "%%b" "%%i"
)
)
Here is a batch script -- let us call it rename-dir-by-owner.bat -- based on the code in my comment:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%U in ('
dir /Q /A:D "%~1" ^| find "<DIR>" ^| findstr /V /R /C:" \.*\.$"
') do (
set "ITEM=%%U"
setlocal EnableDelayedExpansion
set "ITEM=!ITEM:*<DIR>=!" & set "ITEM=!ITEM:*\=!"
for /F "tokens=1,* delims= " %%O in ("!ITEM!") do (
endlocal
ECHO ren "%~dp1%%P" "%%O"
setlocal
)
endlocal
)
endlocal
exit /B
To use this script, provide the directory containing the ones subject to rename as a command line argument -- like this, for instance, supposing the directory is called parent-folder:
rename-dir-by-owner.bat "parent-folder"
The upper-case ECHO command is there for testing purposes; remove it as soon as you actually want to rename any items.
Explanation
The output of the core dir /Q /A:D command line used in the above script looks similar to this:
Volume in drive D has no label.
Volume Serial Number is XXXX-XXXX
Directory of D:\Data
2016/01/01 00:00 <DIR> NT AUTHORITY\SYSTEM .
2016/01/01 00:00 <DIR> BUILTIN\Administrators ..
2015/07/01 01:00 <JUNCTION> NT AUTHORITY\SYSTEM AppData [C:\Users\aschipfl\AppData\Roaming]
2016/03/21 20:00 <DIR> HOST\aschipfl Documents
2016/05/18 23:00 <DIR> HOST\aschipfl Drawings
2016/04/01 13:00 <DIR> HOST\aschipfl Projects
0 File(s) 0 bytes
6 Dir(s) 2'147'483'648 bytes free
The find command filters out all lines that do not contain <DIR> (which marks directories), findstr removes the dummy directories . (current) and .. (parent). So the following lines remain:
2016/03/21 20:00 <DIR> HOST\aschipfl Documents
2016/05/18 23:00 <DIR> HOST\aschipfl Drawings
2016/04/01 13:00 <DIR> HOST\aschipfl Projects
These lines are captured by the outer for /F loop, each one is stored in variable ITEM. Afterwards everything up to the portion <DIR> is removed, then everything up to the (first) \ is cut off. The remaining content of ITEM is now parsed with another for /F loop, which extracts everything in front of the first white-spaces, so the user name of the owner is retrieved; behind the white-spaces is the directory name. Both string parts are passed over to the ren command finally (once ECHO is away).
With this approach the result does (almost) not depend on the locale and region settings of the system, so a quite general solution is achieved. However, this batch program leads to unexpected results if a user name contains white-spaces, but such is not recommended by Microsoft anyway -- consult this article: Creating User and Group Accounts, section "Rules for Logon Names".

Rename file to creation time (batch file only)

Not sure this is possible with only a batch file.
I have a file named BaseFile.7z location is E:\Backup\C Drive Zip\BaseFile.7z
Is it possible to create a batch command that renames the file with its creation date? For example BaseFile - 02-19-2015.7z
I currently have a command that renames the file with the current date which I pasted below for reference, but thats not exactly what I'm looking for. I need creation date.
RENAME "E:\Backup\C Drive Zip\Jaipur.txt" "BaseFile - %date:/=-%.txt"
#ECHO OFF
SETLOCAL
SET "filename=U:\sourcedir\zzz.zzz"
IF NOT EXIST "%filename%" ECHO "%filename%" NOT found&GOTO :eof
SET "datepart="
FOR /f "tokens=1-3delims=/-:" %%a IN ('dir /tc "%filename%"') DO IF "%%c" neq "" SET "datepart=%%a-%%b-%%c"
FOR /f %%a IN ("%filename%") DO FOR /f %%d IN ("%datepart%") DO ECHO(REN "%%a" - "%%~na %%d%%~xa"
GOTO :EOF
The required REN command is merely ECHOed for testing purposes. After you've verified that the command is correct, change ECHO(REN to REN to actually rename the file.
Note that there is general sloppiness in the use of date-references. There are three dates on each file - actual create date (use /tc), last access (/ta) and last-written (/tw).
The process locates the file, then reads a dir listing with the appropriate date selected. The only or last line in the listing that will contain a third non-empty token is the date/time of the file in question, so datepart will acquire yyyy-mm-dd hh
the for/f %%a then applies the full filename to %%a ready for partitionig into its components and the for/f %%d assigns the first token from datepart (ie up to the space) into %%d.
Bang the components together, and the resut is reported...

list with all dirs + date of file with oldest last modified date

been doing research all day and I probably could have done this manually but I just want to learn how to do it to expand my knowledge
REQUIREMENTS:
I have a folder with 11xxx subfolders, I need to know when the oldest file within each of these subfolders was last modified
so far I tried to use the dir command to get a list of all folders and the last modified date of each of the files within a folder
echo Starting...
#echo off
if exist files.txt (del files.txt)
dir /on /s /tw /a-d | find /v "<DIR> ." | find /v "File(s)" > files.txt
if exist files1.txt (del files1.txt)
For /F "delims=" %%A in (files.txt) Do Echo %%A >> files1.txt
if exist files2.txt (del files2.txt)
For /F "skip=2 delims=*" %%A in (files1.txt) Do Echo %%A >> files2.txt
#echo on
echo Finishing...
del files.txt
del files1.txt
ren files2.txt files.txt
quit
ok so the above gave me a txt file in this format
Directory of C:\TEMP
2013/12/05 05:30 PM 22,528 6N85.mst
2011/06/21 12:01 PM 14,108,096 CitrixOnlinePluginWeb.exe
2014/02/19 01:59 PM 448 extract.cmd
2014/02/19 03:42 PM 0 files.txt
2011/08/04 08:41 AM 216 GLF1C8.tmp
2011/08/04 08:41 AM 2,630 GLF1C9.tmp
2011/08/04 08:41 AM 54 GLF1CA.tmp
2011/08/04 08:41 AM 64 GLF1CB.tmp
2011/07/05 12:29 PM 239,174 ITMURebootMSG.EXE
2013/11/28 04:20 PM 2,434,048 msxml.msi
2013/11/28 12:59 PM 2,066,376 msxml4-KB2758694-enu.exe
2004/04/15 10:10 AM 79 process.bat
2012/08/02 12:43 AM 4,594 process.log
2003/11/04 10:17 AM 376 procs.vbs
2014/02/18 03:32 AM 16,391 WakeUpAgt.LO_
2014/02/19 12:04 PM 9,247 WakeUpAgt.LOG
2005/03/09 09:40 AM 4,630,256 WindowsXP-KB895200-x86-ENU.exe
2005/10/12 02:06 PM 4,934,896 WINDOWSXP-KB902400-X86-ENU.exe
2006/05/25 12:12 PM 1,307,376 WindowsXP-KB913580-x86-ENU.exe
Total Files Listed:
0 Dir(s) 81,741,336,576 bytes free
I opened the txt file within excel to get the first 10 chars of each line to get the date in col A,
IMO this approach is wrong, maybe I should be doing it in a different way, anyone care to help?
You're on the right track. The built-in dir command, as you found, can do your sorting for you. If you only care about the date of the oldest file, let it sort by date modified (descending) and get the last entry in the list. This should do what you're after, I think:
for /f %%x in ('dir /b /o-d /a-d') do set OLDESTFILE=%%~fx last modified at %%~tx
echo %OLDESTFILE%
Let me break this down.
The switches to the dir command will give you a list of files only (/a-d), in "brief" form (/b - just a list of files, not the typical full dir output), and will sort that list by date, descending (/o-d).
The for loop that wraps around that iterates over each of these files and sets an environment variable to the text in the format:
C:\TEMP\WindowsXP-KB913580-x86-END.exe last modified at 2006/05/25 12:12 PM
You can read for /? for all of the gritty details about the other ~ modifiers you can use.
If you run this with echo on, you'll see that it actually sets this environment variable each time through the loop, overwriting it with each subsequent iteration. That's ok by us, though, since we only really want the last entry anyway.
Now, if you really only want the date and not the time, that's slightly trickier. You'll need to use a slightly uglier loop like this:
for /f %%x in ('dir /b /o-d /a-d') do (
for /f "tokens=1" %%a in ("%%~tx") do (
set OLDESTFILE=%%~fx last modified on %%a
)
)
echo %OLDESTFILE%
The inner for loop here takes the date and time (e.g., 2006/05/24 12:12) as a list of arguments. Since cmd uses spaces as delimiters by default, this gives you two tokens, 2006/05/24 and 12:12. By specifying tokens=1 you explicitly tell for that you only care about the first of those: the date*.
Hope this gets you going on the right track. Now that you have the tricky part, you can wrap all of this in a loop that gets you the list of directories you care to run this in.
*Pedantically speaking, you don't actually need the tokens=1 there, since %%a would only refer to the first token anyway, and the time would be in %%b, but I thought it would be useful for illustrative purposes.
first of all, thank you #Mark for helping me understand the for loops in dos, I was having trouble with them yesterday and I just couldn't figure out how they worked but now I think I understand!
one of the problems I found with %%~tx was that it didn't extract the last modified date, only the last accessed date, maybe I'm wrong but I figured I'd try a different approach anwyay
::delete any files called list.txt if they exist
if exist list.txt (del list.txt)
::loop through all directories including sub-directories
for /d /r %%x in (*) do (
if exist listTemp1.txt (del listTemp1.txt)
::loop through each file within directory, show time last written, sort desc
for /f "delims=" %%y in ('dir "%%x" /tw /o-d') do (
::append listTemp1.txt with list of files
echo %%y >> listTemp1.txt
)
if exist listTemp2.txt (del listTemp2.txt)
::append listTemp2.txt with lines containing / in the dates
find "/" listTemp1.txt >> listTemp2.txt
::loop through listTemp2.txt to get last line of file, no delims as the first space is after date and we only need date, set var OLDFile with date and current folder
for /f %%z in (listTemp2.txt) do set OLDFile=%%z %%x
::append list.txt with OLDFile
call echo %%OLDFile%% >> list.txt
)
if exist listTemp1.txt (del listTemp1.txt)
if exist listTemp2.txt (del listTemp2.txt)
the above script gave me the exact result I wanted, which was <date of oldest file within folder> <folder>
2014/02/20 C:\TEMP\folder 1
2014/02/19 C:\TEMP\folder 2
2014/02/19 C:\TEMP\folder 1\folder 2
I created temporary txt files since I couldn't pipe for loop results (possible?)
anyways, thanks again #Mark, couldn't have figured out how to do this without your help examples and most importantly the break down which helped me understand the code!

Resources