• Announcements

    • xper

      MSFN Sponsorship and AdBlockers!   07/10/2016

      Dear members, MSFN is made available via subscriptions, donations and advertising revenue. The use of ad-blocking software hurts the site. Please disable ad-blocking software or set an exception for MSFN. Alternatively, become a site sponsor and ads will be disabled automatically and by subscribing you get other sponsor benefits.
tomasz86

Copy only files that have newer version?

31 posts in this topic

CoffeeFiend,

has your code proved stable?

I would be very interested in testing your tool (and it would help me a lot as using xcopy/d is definitely not the best way to determine which file is newer :/).

0

Share this post


Link to post
Share on other sites

has your code proved stable?

It never was about stability. It was just a "make sure everything works 100%" thing, where we test every possible combination. The tool itself is pretty simple so it's quick and easy to write, it's the testing that's a lot of work.

It's a lot of work to find different files with different version formats, NE executables (executables with a version but without a PE timestamp) and so on. Only then to make dozens of variants from them by hand (editing both timstamps and both version tags) so it can be fully tested. Either I would have to do all the work using a hex editor, or I would have to write another program to generate the numerous variants (from various suitable files you have to find first). Also, as the files in both directories have the same filenames, sizes and so on, you have to use hashes to see which one is kept. So I would have to make lists of the different versions of the source files and their specific infos and hashes so the results can be verified by hand. It's boring, tedious, mind-numbing, repetitive, error-prone work that would take hours and as such I haven't worked on it since.

At least if I had a list of files with different "formats" to start working from. I can't say I feel much like spending all Saturday afternoon browsing through system32 hoping to find what's needed to get started... Especially when I have absolutely no use for the tool.

Edit: and without the testing then it's mostly worthless. There would be no point in using a tool that "hopefully copies what it should", not being able to trust it. Nor is there a point handing him a tool that hasn't passed basic tests yet.

0

Share this post


Link to post
Share on other sites

@CoffeeFiend, I think that tomasz86 said he would be glad to test your code on the files he uses. Since he is familiar with those files, and he is the one that would benefit from the code, it seems that would make sense.

Cheers and Regards

Edited by bphlpt
0

Share this post


Link to post
Share on other sites

In the end I've managed to prepare this primitive script:

SETLOCAL ENABLEDELAYEDEXPANSION
SET SOURCEDIR=
SET DESTINATIONDIR=
FOR /F %%I IN ('DIR/A-D/B "%SOURCEDIR%"') DO (
IF EXIST "%DESTINATIONDIR%\%%I" (
FOR /F "tokens=5" %%J IN ('FILEVER "%SOURCEDIR%\%%I"') DO IF NOT "%%J"=="-" (
FOR /F "tokens=5" %%J IN ('FILEVER "%SOURCEDIR%\%%I"') DO SET SOURCEVER=%%J
FOR /F "tokens=5" %%J IN ('FILEVER "%DESTINATIONDIR%\%%I"') DO SET DESTINATIONVER=%%J
FOR /F "tokens=1 delims=." %%I IN ("!SOURCEVER!") DO SET SOURCEVER1=%%I
FOR /F "tokens=2 delims=." %%I IN ("!SOURCEVER!") DO SET SOURCEVER2=%%I
FOR /F "tokens=3 delims=." %%I IN ("!SOURCEVER!") DO SET SOURCEVER3=%%I
FOR /F "tokens=4 delims=." %%I IN ("!SOURCEVER!") DO SET SOURCEVER4=%%I
FOR /F "tokens=1 delims=." %%I IN ("!DESTINATIONVER!") DO SET DESTINATIONVER1=%%I
FOR /F "tokens=2 delims=." %%I IN ("!DESTINATIONVER!") DO SET DESTINATIONVER2=%%I
FOR /F "tokens=3 delims=." %%I IN ("!DESTINATIONVER!") DO SET DESTINATIONVER3=%%I
FOR /F "tokens=4 delims=." %%I IN ("!DESTINATIONVER!") DO SET DESTINATIONVER4=%%I
IF !SOURCEVER1! GTR !DESTINATIONVER1! MOVE "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"
IF EXIST "%DESTINATIONDIR%\%%I" IF !SOURCEVER2! GTR !DESTINATIONVER2! MOVE "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"
IF EXIST "%DESTINATIONDIR%\%%I" IF !SOURCEVER3! GTR !DESTINATIONVER3! MOVE "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"
IF EXIST "%DESTINATIONDIR%\%%I" IF !SOURCEVER4! GTR !DESTINATIONVER4! MOVE "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"
) ELSE (
XCOPY/DY "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"
)
)
)
PAUSE

You just need to set the two variables - SOURCEDIR & DESTINATIONDIR. You will also need Filever.exe. The one from Windows Server 2003 Service Pack 2 32-bit Support Tools works fine.

Edit: Even simpler:

SETLOCAL ENABLEDELAYEDEXPANSION
SET SOURCEDIR=
SET DESTINATIONDIR=
FOR /F %%I IN ('DIR/A-D/B "%SOURCEDIR%"') DO (
IF EXIST "%DESTINATIONDIR%\%%I" (
FOR /F "tokens=5" %%J IN ('FILEVER "%SOURCEDIR%\%%I"') DO IF NOT "%%J"=="-" (
FOR /F "tokens=5" %%J IN ('FILEVER "%SOURCEDIR%\%%I"') DO SET SOURCEVER=%%J
FOR /F "tokens=5" %%J IN ('FILEVER "%DESTINATIONDIR%\%%I"') DO SET DESTINATIONVER=%%J
FOR /F "tokens=1-4 delims=." %%I IN ("!SOURCEVER!") DO (
SET SOURCEVER1=%%I
SET SOURCEVER2=%%J
SET SOURCEVER3=%%K
SET SOURCEVER4=%%L
)
FOR /F "tokens=1-4 delims=." %%I IN ("!DESTINATIONVER!") DO (
SET DESTINATIONVER1=%%I
SET DESTINATIONVER2=%%J
SET DESTINATIONVER3=%%K
SET DESTINATIONVER4=%%L
)
IF !SOURCEVER1! GTR !DESTINATIONVER1! COPY/Y "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"
IF EXIST "%DESTINATIONDIR%\%%I" IF !SOURCEVER2! GTR !DESTINATIONVER2! COPY/Y "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"
IF EXIST "%DESTINATIONDIR%\%%I" IF !SOURCEVER3! GTR !DESTINATIONVER3! COPY/Y "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"
IF EXIST "%DESTINATIONDIR%\%%I" IF !SOURCEVER4! GTR !DESTINATIONVER4! COPY/Y "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"
) ELSE (
XCOPY/DY "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"
)
)
)
PAUSE

And a little bit more explanation:

If you don't split the file version into 4 values then doing something like this:

IF 5.2.3790.620 GTR 5.2.3790.4110 COPY/Y "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"

will actually result in the first file being copied over the second one, i.e. it will think that "5.2.3790.620" is greater than "5.2.3790.4110". On the other hand, if you split the values and do

IF 620 GTR 4110 COPY/Y "%SOURCEDIR%\%%I" "%DESTINATIONDIR%"

then it will not be copied because 4110 > 620. This is a real life example I've just tested here (the file being hhctrl.ocx).

Edited by tomasz86
0

Share this post


Link to post
Share on other sites
Usage: WhateverProgName src dst" format, we can use a better algorithm:

if PE get the PETimestamp;

If hex version of src file is newer (and if PE, if PETimestamp(src) is >= PETimestamp(dst)) then copy src file to dst folder; else

If hex version of src file is newer (and if PE, if PETimestamp(src) is < PETimestamp(dst)) then throw error and skip file; else

If exist text version and text version of src file is newer (and if PE, if PETimestamp(src) is >= PETimestamp(dst)) then copy src file to dst folder; else

If exist text version and text version of src file is newer (and if PE, if PETimestamp(src) is < PETimestamp(dst)) then throw error and skip file; else

If both versions are the same and if PE, the PE timestamp of src file is newer then copy src file to dst folder; else

else just skip file.

This catches and points out the blorky cases that may happen as, for instance, the infamous oleaut32.dll v. 2.40.4522.0 (see post #14, above).

Well, here I am, back to the subject of PETimestamps... When one needs to determine it, what options are there? Just two:

1. Use the latest version of Matt Pietrek's great PEDUMP.EXE console application.

This has the advantage it can be used in batch files or CMD scripts, but it requires some tricks because PEDUMP gives just too much information besides the sought-for PETimestamp, so filtering, possibly twice, with FIND will be required... and moreover it is based in a WIN32 api function that corrects time for the user machine's currently set Timezone (and Summer time, if applicable), so that the times become confusing, when comparing results from different users across the world. On the bright side, it does also show the hexadecimal unix time string, as it appears in the PE Optional Header.

2. Use MiTeC's great EXE Explorer (v. 1.0, because the newest v. 1.3 is buggy).

This has the downside it's a GUI application, so not usable in batch files or CMD scripts. It also does not show the hexadecimal unix time string, as it appears in the PE Optional Header. They've taken care to display time in GMT (aka Zulu = UTF), although they do not ever mention it (they should). However, they've decided to show dates as "aa/bb/yyyy", where "y" is the year, while "a" and "b" may be either the day and month in this order or in the reverse, depending on each user's machine's settings for the short date format, thereby also becoming confusing, when comparing results from different users across the world.

So, neither of the available solutions really is satisfactory, IMO, and that prompted me to write my own application for this, using an unambiguous format for the time and date string, and also presenting the hexadecimal unix time, together with the file name, all this in just one line. And it also supports "*.*", of course! I called it, rather unimaginatively, PETmStp (attached below), and here's hoping it will be as useful as I anticipated it should be. Please do report any bugs found.

PETmStp.7z

0

Share this post


Link to post
Share on other sites

Thanks, dencorso :) I'll try it out as soon as possible.

I've prepared an updated/fixed version of the script I posted above:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET SOURCEDIR=
SET DESTINATIONDIR=
IF EXIST "%DESTINATIONDIR%" (
FOR /F %%I IN ('DIR/A-D/B "%SOURCEDIR%"') DO (
IF EXIST "%DESTINATIONDIR%\%%I" (
FOR /F "tokens=5" %%J IN ('FILEVER "%SOURCEDIR%\%%I"') DO IF NOT "%%J"=="-" (
FOR /F "tokens=5" %%J IN ('FILEVER "%SOURCEDIR%\%%I"') DO SET SOURCEVER=%%J
FOR /F "tokens=5" %%J IN ('FILEVER "%DESTINATIONDIR%\%%I"') DO SET DESTINATIONVER=%%J
FOR /F "tokens=1-4 delims=." %%I IN ("!SOURCEVER!") DO (
SET SOURCEVER1=%%I
SET SOURCEVER2=%%J
SET SOURCEVER3=%%K
SET SOURCEVER4=%%L
)
FOR /F "tokens=1-4 delims=." %%I IN ("!DESTINATIONVER!") DO (
SET DESTINATIONVER1=%%I
SET DESTINATIONVER2=%%J
SET DESTINATIONVER3=%%K
SET DESTINATIONVER4=%%L
)
IF !SOURCEVER! EQU !DESTINATIONVER! (
XCOPY/DY "%SOURCEDIR%\%%I" "%DESTINATIONDIR%" >NUL
FOR /F %%J IN ('XCOPY/DY "%SOURCEDIR%\%%I" "%DESTINATIONDIR%" ^| FIND "0"') DO IF !ERRORLEVEL! NEQ 0 ECHO %SOURCEDIR%\%%I
DEL/Q "%SOURCEDIR%\%%I"
)
IF EXIST "%SOURCEDIR%\%%I" IF !SOURCEVER1! GTR !DESTINATIONVER1! (
MOVE/Y "%SOURCEDIR%\%%I" "%DESTINATIONDIR%" >NUL
ECHO %SOURCEDIR%\%%I
)
IF EXIST "%SOURCEDIR%\%%I" IF NOT !DESTINATIONVER1! GTR !SOURCEVER1! IF !SOURCEVER2! GTR !DESTINATIONVER2! (
MOVE/Y "%SOURCEDIR%\%%I" "%DESTINATIONDIR%" >NUL
ECHO %SOURCEDIR%\%%I
)
IF EXIST "%SOURCEDIR%\%%I" IF NOT !DESTINATIONVER1! GTR !SOURCEVER1! IF NOT !DESTINATIONVER2! GTR !SOURCEVER2! IF !SOURCEVER3! GTR !DESTINATIONVER3! (
MOVE/Y "%SOURCEDIR%\%%I" "%DESTINATIONDIR%" >NUL
ECHO %SOURCEDIR%\%%I
)
IF EXIST "%SOURCEDIR%\%%I" IF NOT !DESTINATIONVER1! GTR !SOURCEVER1! IF NOT !DESTINATIONVER2! GTR !SOURCEVER2! IF NOT !DESTINATIONVER3! GTR !SOURCEVER3! IF !SOURCEVER4! GTR !DESTINATIONVER4! (
MOVE/Y "%SOURCEDIR%\%%I" "%DESTINATIONDIR%" >NUL
ECHO %SOURCEDIR%\%%I
)
) ELSE (
XCOPY/DY "%SOURCEDIR%\%%I" "%DESTINATIONDIR%" >NUL
FOR /F %%J IN ('XCOPY/DY "%SOURCEDIR%\%%I" "%DESTINATIONDIR%" ^| FIND "0"') DO IF !ERRORLEVEL! NEQ 0 ECHO %SOURCEDIR%\%%I
)
) ELSE (
MOVE "%SOURCEDIR%\%%I" "%DESTINATIONDIR%" >NUL
IF !ERRORLEVEL! EQU 0 ECHO %SOURCEDIR%\%%I
)
)
) ELSE (
MD %DESTINATIONDIR%
COPY %SOURCEDIR%\*.* %DESTINATIONDIR% >NUL
FOR /F %%I IN ('DIR/A-D/B %SOURCEDIR%') DO ECHO %SOURCEDIR%\%%I
)
PAUSE

Be careful because this one actually moves some of the files.

Edited by tomasz86
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.