views:

1093

answers:

2

In DOS batch files, the method of achieving certain things is somewhat obfuscated. Fortunately, there is a fantastic reference site for DOS batch scripting: Simon Sheppard's SS64. (The same site also has plenty of information about Bash.)

One difficulty is branching execution based on whether a directory is empty. The obvious if exist "%dir%\*.*" doesn't work. But it can be done with this conditional execution trick:

( dir /b /a "%dir%" | findstr . ) > nul && (
  echo %dir% non-empty
) || (
  echo %dir% empty
)

Another awkward problem is branching according to file contents. Again that can be done like this:

( fc /B "%file1%" "%file2%" | find "FC: no differences encountered" ) > nul && (
  echo "%file1%" and "%file2%" are the same
) || (
  echo "%file1%" and "%file2%" are different
)

So, my question is:
Is there a way to do branch according to the time-stamps of files?

This is the sort of thing I want:

REM *** pseudo-code!
if "%file1%" is_newer_than "%file2%" (
  echo "%file1%" is newer
) else if "%file1%" is_older_than "%file2%" (
  echo "%file2%" is newer
) else (
  echo "%file1%" and "%file2%" are the same age
)

Thanks.

+3  A: 

seriously, you should start to learn something else. Its not a joke. DOS(cmd.exe) seriously lacks date manipulation capabilities and many more deficiencies. Here's the next better alternative natively provided besides DOS batch, vbscript

Set objFS = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strFile1 = objArgs(0)
strFile2 = objArgs(1)
Set objFile1 = objFS.GetFile(strFile1)
Set objFile2 = objFS.GetFile(strFile2)
If objFile1.DateLastModified < objFile2.DateLastModified Then
    WScript.Echo "File1: "&strFile1&" is older than "&strFile2
Else
    WScript.Echo "File1: "&strFile1&" is newer than "&strFile2
End If

run it on command line

C:\test>dir
 Volume in drive C has no label.
 Volume Serial Number is 08AC-4F03

 Directory of C:\test

11/06/2009  07:40 PM    <DIR>          .
11/06/2009  07:40 PM    <DIR>          ..
11/06/2009  06:26 PM               135 file
11/02/2009  04:31 PM             4,516 m.txt

C:\test>cscript /nologo test.vbs file m.txt
File1: file is newer than m.txt

Of course, in newer versions of windows, you may want to try out Powershell...

ghostdog74
Thanks. You're right about DOS. For personal scripting, I use Bash in Cygwin. When writing small utilities to be used by the team, I need to use a language available to all. Python is quite widespread here. (It also has the cross-platform advantage.) But, Python is a "scripting language" rather than a "shell language", and so spawning sub-processes requires more work. Your suggestion of VBScript is a good one; perhaps I should start to get to know that. I have avoided the "Powershells" deliberately, because Microsoft don't seem to be able to make up their minds to support one properly.
Rhubbarb
@rhubbarb - Powershell comes installed on Windows 7 and Windows Server 2008 R2 and I think Powershell is also used pretty extensively by Exchange 2007. So it's definitely supported properly now. It's worth checking out as it's pretty awesome.
Dave Webb
If you are using Python, you should use it throughout. It doesn't matter whether its a scripting language or shell language. Its just a name. What's important is, Python (and its nemesis Perl) can do almost everything shell or (DOS) can. Moving/copying files, parsing, grabbing web page...practically, you just only need 1 good and easy to use tool to do all your admin/programming tasks.AS for the above checking for older/newer files, you can use Python's os.getmtime() to check modified time.
ghostdog74
ghostdog74: Thanks, I agree. I use Python a great deal. But it genuinely is not so easy for certain tasks, such as launching external programs (such as Subversion), and capturing, redirecting and piping the results. DOS has pipes. Bash has pipes (|) and back-ticks (`...`). Python can do all this, but it involves choosing from the plethora of 'popen'/'subprocess' modules. There might be a better-encapsulated, better-abstracted method in Python, but I don't know it.
Rhubbarb
when such a situation occurs, always the first thing to go for, check pypi (or search internet) for modules that do the thing you want. I am sure you can find modules for svn that works with Python. that way you don't need to call external process. If really no choice you have to use subprocess module, you would still have the advantage of Python's excellent parsing capabilities.:)
ghostdog74
+3  A: 

You can find the newer of two files with one line of batch script. Just list the files in date order, oldest first, which means the last file listed must be the newer file. So if you save the file name each time, the last name put in your variable will be the newest file.

For, example:

SET FILE1=foo.txt
SET FILE2=bar.txt
FOR /F %%i IN ('DIR /B /O:D %FILE1% %FILE2%') DO SET NEWEST=%%i
ECHO %NEWEST% is (probably) newer.

This unfortunately doesn't cope with the date stamps being the same. So we just need to check if the files have the same date and time stamp first:

SET FILE1=foo.txt
SET FILE2=bar.txt

FOR %%i IN (%FILE1%) DO SET DATE1=%%~ti
FOR %%i IN (%FILE2%) DO SET DATE2=%%~ti
IF "%DATE1%"=="%DATE2%" ECHO Files have same age && GOTO END

FOR /F %%i IN ('DIR /B /O:D %FILE1% %FILE2%') DO SET NEWEST=%%i
ECHO Newer file is %NEWEST%

:END
Dave Webb