BATCH script: Cannot get modified date for file in nested loop - date

I am having trouble getting the date modified for my file from within a nested loop.
I am running this batch script:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
net use S: \\devfs\edcsrc\epoletto\campusanyware
SET CLIENTS= DEMO
FOR %%a in (%CLIENTS%) DO (
S:
CD AD
FOR %%B in (*.cbl) DO (
set file=%%B
echo !file!
for %%c in (!file!) do (echo %%~ta))
)
pause
net use S: /delete /Y
ECHO.
Here is my output:
The command completed successfully.
ad1.cbl
ECHO is off.
ad2.cbl
ECHO is off.
ad3.cbl
ECHO is off.
Press any key to continue . . .
All of my file names are correct, but when the script goes into the the third FOR loop (for %%c in (!file!) do (echo %%~ta))), I cannot get the date/time modified for my file.
As a proof of concept, I tried this same logic from the command line from within the directory:
for %B in (*.cbl) DO (for %a in (%B) do echo %~ta)
And my output from that command was (including initial command):
V:\>for %B in (*.cbl) DO (for %a in (%B) do echo %~ta)
V:\>(for %a in (ad1.cbl) do echo %~ta )
V:\>echo 05/02/2017 11:32 AM
05/02/2017 11:32 AM
V:\>(for %a in (ad2.cbl) do echo %~ta )
V:\>echo 04/18/2017 02:04 PM
04/18/2017 02:04 PM
V:\>(for %a in (ad3.cbl) do echo %~ta )
V:\>echo 04/27/2017 11:46 AM
04/27/2017 11:46 AM
I'm confused as to why I can't get these dates from within my script. My ultimate goal is to check the date for each file and then execute another command dependent on that date. Right now I'm just trying to verify I can get the date using echo. Any suggestions are appreciated!
Thank you!

Instead of
for %%c in (!file!) do (echo %%~ta))
use
for %%c in (!file!) do (echo %%~tc))
because you want the modified time of %%c, not of %%a.
:)

Related

Using %date% in batch script

I want to have some code like this:
if %date% equ "Mon" echo do this do that
but the cmd window closes after encountering this code, even if I put
pause
after it.
How do I fix this?
Here's a complete cmd file that will give you what you need. The important bit is all in the getDow function and, hopefully, it's commented well enough to understand. First, the test harness:
#echo off
rem Test harness bit - just get current date and compare with getDow.
date /t
call :getDow num long short
echo Day of week is %num%, %long%, %short%
goto :eof
The function itself is:
rem Usage: call :getDow <num> <long> <short>
rem <num> will receive the numeric form (0-6).
rem <long> will receive the long form (e.g., Monday).
rem <short> will receive the short form (e.g., Mon).
:getDow
rem Create local scope to prevent information leakage.
setlocal enableextensions enabledelayedexpansion
rem Create array for translation.
set idx=0
for %%a in (Sunday Monday Tuesday Wednesday Thursday Friday Saturday) do (
set dow[!idx!]=%%a
set /a "idx += 1"
)
rem Get the numeric day of week, mmi command will
rem output 'DayOfWeek=N' and we just extract N.
for /f "tokens=2 delims==" %%a in ('WMIC Path Win32_LocalTime Get DayOfWeek /value ^| findstr "DayOfWeek="') do (
set localNum=%%a
)
set localStr=!dow[%localNum%]!
rem Properly end scope but let selected information leak.
endlocal&&set %1=%localNum%&&set %2=%localStr%&&set %3=%localStr:~0,3%
goto :eof
A sample run of that script gives:
Tue Jun 05
Day of week is 2, Tuesday, Tue
You probably want to use:
IF /I "%DATE:~,3%"=="Mon" (Echo Do this
Echo Do that)
Or possibly:
IF NOT "%DATE:Mon=%"=="%DATE%" (Echo Do this
Echo Do that)
However neither of those are safe or robust methods in anything other than your specific current user environment.
This is how I'd get the day of the week into a variable using a batch file with WMIC:
For /F %%A In ('WMIC Path Win32_LocalTime Get DayOfWeek') Do For %%B In (
Monday.1 Tuesday.2 Wednesday.3 Thursday.4 Friday.5 Saturday.6 Sunday.0
) Do If "%%~xB"==".%%A" Set "WDName=%%~nB"
Line 2 can be optionally adjusted to start with Sunday.0 Monday.1 etc. if necessary or Lunes.1 Martes.2 etc. depending upon your language.
You could then use:
If "%WDName%"=="Monday" (Echo Do this
Echo Do that)
Although (Get-Date).DayOfWeek in PowerShell seems so much simpler.

Batch file check file get updated to today's date(System Date)

I want to create a batch to check if the file have been modified to today's date, what i did was to "bring in a system's date and compare it with the modified date, if they match, then trigger something. My batch file works well and displays two right dates, but the IF statement saying the date mismatch.
#ECHO OFF
for /f "tokens=1,2,3,4 delims=. " %%i in ('date /t') do set date=%%k%%j
echo %date%
pause
FOR %%a IN (D:\MyFile.txt) DO SET FileDate=%%~ta
set DATEONLY=%FileDate:~0,10%
echo %DATEONLY%
pause
if DATEONLY==date (
echo date ok
)
else (
cls
ECHO Wrong
)
PAUSE
There are the following problems:
do not use variable name date as this is a built-in variable containing the current date (type set /? for help);
the first for statement is useless, because %date% is already available;
the strings DATEONLY and date are compared literally in your if statement, you need to state %DATEONLY%==%date% instead;
the else statement must be in the same line as the closing parenthesis of the if body (type if /? for help);
So try this:
#ECHO OFF
echo %date%
pause
FOR %%a IN (D:\MyFile.txt) DO SET FileDate=%%~ta
set DATEONLY=%FileDate:~0,10%
echo %DATEONLY%
pause
if %DATEONLY%==%date% (
echo date ok
) else (
ECHO Wrong
)
PAUSE
Note: Regard that all those dates in the batch file are locale-dependent.
Here is a completely different approach:
forfiles /P . /M MyFile.txt /D +0 /C "cmd /C echo #fdate #file"
The forfiles command is capable of checking the file date. In the above command line, it:
walks through the current directory (.),
lists all files named MyFile.txt (of course there is onlyone),
but only if it has been modified +0 days after today,
and then executed the command line after the /C switch.
If MyFile.txt has been modified today (or even in future), the given command line is executed;
if it has been modified earlier than today, an error message is displayed and ERRORLEVEL is set to 1.
Notice that forfiles is not a built-in command and might not be available on your operating system.

Syntax of the "for" command: whats wrong with line 10 in following batch file?

1 echo off
2
3 echo Please enter a date
4 set /p a=
5 echo %a%
6 for /D %%d in (M:\Serienbriefauftrag\*) do (
7 if not exist %%d\Erledigt\*.bat echo %%d
8 )
9 pause
10 for /d %%b in (dir M:\Serienbriefauftrag\%%d /T:C)
11 echo %%b
12 pause
The Code works fine until line 10 (syntax error) the aim is, to get the creation date of the folder compare it with "%a%" and and if it's under the entered date "%a%", the folder should be moved. but somehow...
found a way to get the creation date
if not exist %%d\Erledigt\*.bat echo %%~td|findstr /i /l
the new task is to make the output "calculateable"
Two things:
1) In line 10 %%d is undefined (empty), since the scope of the first loop (where it is defined) is left in line 8.
You can set another variable to %%d to be able to use it after the loop ends, but be careful. In batch using set in for loops is a bit tricky. To get around the aweful use of delayed variable expansion, I would suggest to you staying inside of the loop while doing your work.
#echo off
set /p a=Please enter a date:
for /d %%d in (M:\Serienbriefauftrag\*) do (
if not exist %%d\Erledigt\*.bat (
:: Do whatever you want with %%d in here
echo "%%d"
)
)
pause
2) The syntax of your second loop is wrong. You are missing the do before the loop body and /d lets the loop iterate over all folders in a specified directory. dir M:\Serienbriefauftrag\%%d /T:C is not a directory but a command.
If you want to iterate over the output of that command, you have to use /f and put the contents of the paranthesis in single quotes, like that ('dir M:\Serienbriefauftrag\%%d /T:C').

Batch file to rename all files in a folder by adding current date/time to beginning of filename

I can't seem to understand how batch files add yyyy/mo/dd/hh/mm/ss to the beginning of filenames. (Using Windows 7) Accuracy to the second is important.
It doesn't actually have to be a batch file, it just has to be a small program which can be executed by Directory Monitor whenever I add files to a folder: http://brutaldev.com/page/Directory-Monitor.aspx
I only imagine that a batch file would be the simplest and most efficient approach, but any other suggestions are welcome.
I work with many sequentially numbered files with overlapping filenames and I need a quick way to rename them whenever I add them to a folder such that there will never be any file with the same name yet they will still remain in sequential order. This is how I thought of adding the current date and time to the beginning of the filename and why seconds are important, since I can easily add multiple sets to a folder in under a minute but certainly not under a second. It would be ideal if the batch file could ignore file extensions and simply add the current date/time to the beginning of any file added to the folder.
The first four lines of this code will give you reliable YY DD MM YYYY HH Min Sec variables in XP Pro and higher.
#echo off
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 "datestamp=%YYYY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%" & set "fullstamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%"
echo datestamp: "%datestamp%"
echo timestamp: "%timestamp%"
echo fullstamp: "%fullstamp%"
:: this line will rename the files in the current folder which haven't already
:: been renamed by checking for the fullstamp format at the start of the line
:: but it will skip this batch file
for /f "delims=" %%a in ('dir /b /a-d ^|findstr /v "^[0-9]*-[0-9]*-[0-9]*_[0-9]*-[0-9]*-[0-9]*" ') do if /i not "%%a"=="%~nx0" ren "%%a" "%fullstamp% - %%a"
pause
#ECHO off
SETLOCAL
IF [%1] NEQ [] goto s_start
:: Author - Simon Sheppard, July 2003
:: Tested for Windows NT, 2K, XP
ECHO STAMPME.cmd
ECHO REName a file with the DATE/Time
ECHO.
ECHO SYNTAX
ECHO STAMPME TestFile.txt
ECHO.
ECHO STAMPME "Test File.txt"
ECHO.
ECHO STAMPME "c:\docs\Test File.txt"
ECHO.
ECHO In a batch file use CALL STAMPME ...
:: To change the filename format just change around the last line below
GOTO :eof
:s_start
SET _file=%~n1%
SET _pathname=%~f1%
SET _ext=%~x1%
::Get the date
:: note ISO 8601 date format would require 4 digit YYYY Year)
FOR /f "tokens=6-8 delims=/ " %%G IN ('NET TIME \\%computername%') DO (
SET _mm=%%G
SET _dd=%%H
SET _yy=%%I
)
:: Get the time
FOR /f "tokens=2-4 delims=:." %%G IN ('cmd /c "time<nul"') DO (
SET _hr=%%G
SET _min=%%H
SET _sec=%%I
GOTO :done
)
:done
ECHO Today is Year: [%_yy%] Month: [%_mm%] Day: [%_dd%]
ECHO The time is: [%_hr%]:[%_min%]:[%_sec%]
REN "%_pathname%" "%_hr%-%_min%-%_sec%#%_file%%_ext%"
This seems to work for me
I'd prefer solutions, that are not dependent to local settings (wmic gives always the same format):
#echo off
setlocal EnableDelayedExpansion
for %%a in (a.*) do (
for /f %%i in ( 'wmic os get localdatetime /value ^|find "Local"' ) do set %%i
set ldt=!LocalDateTime:~0,4!-!LocalDateTime:~4,2!-!LocalDateTime:~6,2!-!LocalDateTime:~8,2!-!LocalDateTime:~10,2!-!LocalDateTime:~12,2!-!LocalDateTime:~15,3!
echo seconds ### ren %%a !LocalDateTime:~0,14!%%a
echo milliseconds ### ren %%a !LocalDateTime:~0,18!%%a
echo with separator ### ren %%a !ldt!-%%a
)

BATCH/CMD: Print each line of a .txt into a variable

Goal: Have every dll file in a computer passed into regsvr32.exe
Accomplished:
cd\
::REM Exports every file and directory (/s) into a file in root of c: called dir.txt with only file names (/b)
dir /s /b>>dir.txt
::REM Now, this will contain every extension type. We only want dll's, so we findstr it into dll.txt:
findstr ".dll$" dir.txt>>dll.txt
The Kink:
Now, if I want to regsvr32.exe "file" every file that is now in dll.txt, I somehow need to get out every individual filename that is individually on each line. I was wondering if there is a third party command line tool that can export each line of the file into a variable. This way, I could:
==========
::REM assume this tool had switches /l for the line number, and /v:"" for variable to use, and used "file" at the end:
set line=1
:loop
set dll=
tool.exe /l %line% /v:"dll" "dll.txt"
::REM We if defined here because if the line doesn't exist in dll.txt, the tool would return nothing to %dll%
if not defined %dll% exit
::REM With the variable defined, we can continue
regsvr32.exe %dll%
set /a line=%line%+1
goto loop
=======================
Then the tool would process each path of each line of the file until it exits automatically, because there would be no more lines. Notice right after loop I set dll to nothing so that 'if not defined' will work each time.
If this type of third-party tool cannot be done, is there a way to do that with for??
I honestly never learned for, and tried to but could never figure it out.
Any help is greatly appreciated!
Sorry if this has already been answered.
EDIT/UPDATE:
I have discovered how I will make this work.
Thanks to: http://pyrocam.com/re-register-all-dlls-to-fix-no-such-interface-supported-error-in-windows-7-after-installing-ie7-standalone/
and : Read a txt line by line in a batch file
The first link shows manually replacing the beginning with regsvr32.exe
The second shows how to use for in this case {also thanks to craig65535 FOR his help :)}
Code:
#echo off
color 1f
title Register .dll
echo.
echo Exporting file list . . .
echo.
cd /d c:
cd\
if exist dll.txt del dll.txt
if exist dir.txt del dir.txt
if exist dll.bat del dll.bat
echo Part 1 of 3 . . .
echo.
dir /s /b>>dir.txt
echo Part 2 of 3 . . .
echo.
findstr ".dll$" dir.txt>>dll.txt
del dir.txt
echo Part 3 of 3 . . .
echo.
for /f "delims=" %%i IN ('type dll.txt') do echo regsvr32.exe /s "%%i">>dll.bat
del dll.txt
echo Ready to begin regsvr32.exe . . .
echo.
pause
echo.
echo Beginning registration . . .
echo *This will take time, close any popups that occur
echo.
call dll.bat
echo.
echo Deleting registration file . . .
if exist dll.bat del dll.bat
echo.
echo DONE.
echo.
pause >nul
The command you want is for /f.
for /f %%f in ('type dll.txt') do regsvr32.exe %%f
That takes the output of type dll.txt and puts one line at a time into %%f. You can then use %%f as an argument for some other command.
If you want to do more than regsvr32.exe %%f, you can write another batch file and call that:
for /f %%f in ('type dll.txt') do call process.bat %%f
process.bat would then receive the filename as %1.