0

I have silly question but, I would like to know how could I do the following with a .bat file or even know if it's possible.

I have a file that someone puts in a folder on a server which is not on my network (but we have access because we are in the domain) so, I have to search for the most recent one and copy it to a folder which IS in my network.

I'm stuck in the part in which you select the "most recent file"

Any ideas will be really wellcome :)

4 Answers 4

1

I recently made a Perl script that does that exactly. When you launch this script, it searches if there's a more recent ZIP file, copies it, extract it, modifies a config file, and launches the EXE. Maybe you don't want to do all this but I'll post it here if you want to modify/use it.

#!/usr/bin/perl
# get_latest_executable.pl v0.5
# Usage: perl get_latest_executable.pl test4|test6 [country] [language]
###############
# YD @ 02/09/2011
# 05/09/2011    Multiple transparent compression options
#               Fixed config file backup
#               Removed useless debug code
# 12/09/2011    Added external configuration file
#               Removed internal arrays with options, script argument is trusted now
# 15/09/2011    Added informing latest executable date
#               More comments and intro
# 19/09/2011    Bug retreiving versions higher than 99 (fixed)
#               Now checking latest executable is done on file creation time and no longer using version
# 27/09/2011    Fixed extra trailing \ on destination path
# 28/09/2011    Added commenting out all user.dll's updateUserConfiguration entry
#               Now user.dll file is parsed until the end, and does not stop when first searched entry is found
###############

use strict;
use File::stat;
use File::Path qw(make_path remove_tree);
use File::Copy;

use constant VERSION => "v0.5";
use constant TIMESTAMP_FORMAT => "%02d:%02d %02d/%02d/%4d"; # Formato del informe de fecha

##########
# Args
##########
use constant MIN_ARGS => 0;
use constant MAX_ARGS => 2;

##########
# Indexes
##########
use constant IDX_TEST4 => 0;
use constant IDX_TEST6 => 1;
my $executable_branch;

##########
# Paths
##########
my $path_source;
# Where to copy the executable in local
my $path_destination;
# Where to search for latest executable
my $path_latest_executable;

##########
# File names
##########
# SGCV10 executable name
my $executable_name = 'gccom.exe';
# SGCV10 config file name
my $config_file = "user.dll";
# Script configuration file
my $config = "config.txt";

##########
# Compressors
##########
my @compressors = ('"C:\Archivos de programa\7-Zip\7z.exe" x -y ', '"C:\Archivos de programa\WinZip\winzip32.exe" -e ');

##########
# SGCV10 configuration
##########
my $do_config_changes = "";
my $backup_prefix = '.bak';
my $country = "es";
my $country_option = '(^COUNTRY=)';
my $lang = "ES";
my $lang_option = '(^LANGUAGE=)';
my $update_option = '^updateUserConfiguration=';

##########
# Script configuration
##########
my $source = '^SOURCE=(.*)\n';
my $destination = '^DESTINATION=(.*)\n';

# Checks arguments received by the script
sub check_args()
{
    if ($#ARGV > MAX_ARGS || $#ARGV < MIN_ARGS)
    {
        print(STDERR "Numero de argumentos incorrecto\n");
        print(STDERR "Uso: perl get_latest_executable.pl test4|test6 [country] [language]\n");
        exit();
    }

    $executable_branch = $ARGV[0];

    if ($#ARGV >= 1)
    {
        $do_config_changes = "1";
        $country = $ARGV[1];
    }

    if ($#ARGV == 2)
    {
        $lang = uc($ARGV[2]);
    }
}

# Returns true if file "a" is newer than file "b"
sub is_newer_version
{
    my ($a_path, $b_path) = @_;
    my $ret = "1";

    if ($b_path ne "")
    {
        my $a_time = stat($a_path)->mtime;
        my $b_time = stat($b_path)->mtime;

        $ret = $a_time > $b_time;
    }

    return $ret;
}

# Receives executable directory
# Returns latest zip full path
sub get_latest_zip_full_path
{
    my $path = shift;
    my $ret;

    if (-d $path)
    {   
        opendir(DH, $path) or die ("No se pudo abrir el directorio: $path\n");
        my @dir = readdir(DH);
        close(DH);
        my $newest = 0;

        for(@dir)
        {
            my $full_path = $path.$_;
            if (-f $full_path && $_ =~ m/zip/i)
            {
                my $cur_file_time = stat($full_path)->mtime;
                if($cur_file_time > $newest)
                {
                    $newest = $cur_file_time;
                    $ret = $full_path;
                }
            }
        }
    }

    return $ret;
}

# Returns true if local executable is OLDER than remote executable, false otherwise
# Creates local directory if not found, deletes older executable .ZIP and directory
sub check_local_delete
{
    my ($local_dir, $local_latest, $remote_path) = @_;
    my $ret = "";

    # Local directory exists
    if(-d $local_dir)
    {
        if (is_newer_version($remote_path, $local_latest))
        {
            print(STDERR "Borrando ejecutable obsoleto: $local_latest\n");

            # Delete older local ZIP
            unlink($local_latest);

            # Delete old directory
            $local_latest =~ s/\.zip//;
            if (-d $local_latest)
            {
                remove_tree($local_latest);
            }
            $ret = "1";
        }
    }
    # Local directory does not exist, create it and return remote newer
    else
    {
        make_path($local_dir);
        $ret = "1";
    }
    return $ret;
}

# Given a full path, returns filename only
sub get_filename_from_full_path
{
    my $full_path = shift;

    my $ret = reverse($full_path);
    $ret =~ m/\\/;
    $ret = $`;
    $ret = reverse($ret);

    return $ret;
}

# Modifies SGCv10 configuration
sub make_config_changes
{
    my $path = shift;
    my $config_path = $path.$config_file;
    if (-f $config_path)
    {
        open(FD, '<'.$config_path);
        my @config = <FD>;
        close(FD);

        # Backup original file (only if not backed up already!!!)
        if (!(-f $config_path.$backup_prefix))
        {
            copy($config_path, $config_path.$backup_prefix);
        }

        # Modify it
        my $i = 0;
        while($i <= $#config)
        {           
            if ($config[$i] =~ /$country_option/)
            {
                $config[$i] = $1.$country."\n";             
            }
            if ($config[$i] =~ /$lang_option/)
            {
                $config[$i] = $1.$lang."\n";
            }
            if ($config[$i] =~ /$update_option/)
            {
                $config[$i] = "//" . $config[$i];
            }
            $i++;
        }   

        # Write it
        open(FD, '>'.$config_path);
        print(FD @config);
        close(FD);
    }
    else
    {
        print(STDERR "WARNING: config file $config_path not found!\n");
    }
}

# Selects best command to decompress with
sub get_best_compressor
{
    my $ret;
    my $i = 0;
    my $found = ""; 
    while($i <= $#compressors && !$found)
    {
        $compressors[$i] =~ m/\"(.*)\"/;
        if (-f $1)
        {
            $ret = $compressors[$i];
            $found = "1";
        }
    }

    if (!$found)
    {
        $ret = -1;
    }

    return $ret;
}

# Reads and applies configuration file
sub read_config
{
    open(FD, '<'.$config) or die "No se encontro el fichero de configuracion $config\n";
    my @config = <FD>;
    close(FD);

    # Source
    my @source_list = grep(/$source/, @config);
    my $src = $source_list[0];
    $src =~ /$source/;
    $src = $1;
    if (substr($src, -1, 1) ne "\\")
    {
        $src .= "\\";
    }
    $path_latest_executable = uc("$src$executable_branch\\");

    # Destination
    my @dest_list = grep(/$destination/, @config);
    $path_destination = $dest_list[0];
    $path_destination =~ /$destination/;
    $path_destination = uc($1);
    if (substr($path_destination, -1, 1) ne "\\")
    {
        $path_destination .= "\\";
    }
}

# Formatea el tiempo
sub format_timestamp
{
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = @_;
    return sprintf(TIMESTAMP_FORMAT, $hour, $min, $mday, $mon+1, $year+1900);
}

# Basurilla
sub intro
{
    print(STDERR "AutoEjecutable " . VERSION . " by Obi Perl Kenobi\n\n");
}

#############
# MAIN
#############

# Show intro
intro();

# Checking arguments
check_args();

# Read configuration file
read_config();

if (!(-d $path_latest_executable))
{
    print(STDERR "No se ha encontrado el directorio origen $path_latest_executable\n");
    exit();
}

# Getting latest executable
my $latest_zip_full_path = get_latest_zip_full_path($path_latest_executable);

# Getting time stamp
my $latest_zip_time = format_timestamp(localtime(stat($latest_zip_full_path)->mtime));

print(STDERR "Ultimo ejecutable disponible: $latest_zip_full_path -> $latest_zip_time\n");

# Checking if latest executable newer than local
$path_destination .= $executable_branch."\\";
if (check_local_delete($path_destination, get_latest_zip_full_path($path_destination), $latest_zip_full_path))
{
    print(STDERR "El ejecutable remoto es mas reciente ($latest_zip_time), copiando... ");
    # Copying executable to local
    copy($latest_zip_full_path, $path_destination);
}
else
{
    print(STDERR "No hay cambios!\n");
}

my $path_aux = $path_destination.get_filename_from_full_path($latest_zip_full_path);
my $local_exe_dir = $path_aux;
$local_exe_dir =~ s/\.zip//;
$local_exe_dir .= "\\";
if (-f $path_aux && !(-d $local_exe_dir))
{
    # Choose extractor
    my $extractor_command = get_best_compressor();
    if ($extractor_command == -1)
    {
        print(STDERR "No se pudo encontrar ningun programa de descompresión. Por favor modifique las rutas en el script si no usa la instalación por defecto\n");
        exit();
    }
    # Extract ZIP
    chdir($path_destination);
    print(STDERR "Extrayendo...\n");
    $extractor_command .= '"' . $path_aux . '"';
    system($extractor_command);
}

chdir($local_exe_dir);

if ($do_config_changes)
{
    print(STDERR "Modificando configuracion para pais $country y lengua $lang...\n");
    make_config_changes($local_exe_dir);
}

my $local_exe = '"' . $local_exe_dir.$executable_name . '"';
print(STDERR "Lanzando el ejecutable $local_exe de las $latest_zip_time\n");
system($local_exe);

The get_latest_zip_full_path() subroutine does what you're asking for.

It uses an external configuration file, as follows:

SOURCE=J:\Ejecutables\
DESTINATION=D:\SGCv10\ejecutables\

This will not work "as is" for your problem. Feel free to modify and use as you wish, as well as ask what you want.

2
  • Thank you very much! I'm from Spain so I won't have issues understanding this. Now I have to figure it out how to modify to suit my needs but seems pretty easy :) Oct 5, 2011 at 10:08
  • I assumed you were from a spanish speaking country by the name ;) Anyway, if you need help on modifying it, don't hesitate to ask. And btw, I forgot to mention you need a Perl interpreter to be able to execute this. I recommend ActivePerl.
    – m0skit0
    Oct 5, 2011 at 10:39
1

You should take a look at robocopy for these types of tasks. It was part of the resource kit in earlier Windows version, but now it is now part foe Win2k8 server and Windows 7. There is a whole set of File Selection Option that help with this task.

1

This will mirror the directory tree. Copy different files from the source, and delete extra files in the destination

ROBOCOPY source destination /MIR

This will copy subdirectories, including empty ones while excluding older files.

ROBOCOPY source destination /E /XO
0

You can try a Windows variant of the Unix remote copy tool rsync, cwRsync:

cwRsync is a yet another packaging of Rsync and Cygwin. You can use cwRsync for fast remote file backup and synchronization. Rsync uses the Rsync algorithm which provides a very fast method for bringing remote files into sync.

It should pretty much meet the need you have stated.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .