views:

212

answers:

4

So I need a Windows Script that I can tell it a directory to go through and it will parse all sub-directories and while in each subdir, will archive all files with a certain file extension and keep it in the same subdir, then move onto the next one.

What's the best way to go about this? Perl Automation Scripting, AutoIt?

Any sample code you guys can give me?

A: 

One solution could be:

my $dirCnt = 0;
traverse_directory('C:\Test');

sub traverse_directory{
    my $directory = shift(@_);  
    $dirCnt++;

    my $dirHandle = "DIR".$dirCnt;    
    opendir($dirHandle, $directory);

    while (defined(my $file = readdir($dirHandle))){
         next if $file =~ /^\.\.?$/;                # skip . and .. ...
         if (-d "$directory\\$file"){  traverse_directory("$directory\\$file");  }
         if ($file =~ /\.txt/){  #find txt files, for example

             print "$file\n";      #do something with the text file here
         }
    }
    closedir($dirHandle);
}
Narthring
+2  A: 

Perl is more powerful than batch scripts but since Perl is not included with windows it seems overkill for tasks such as this one. This should for example work:

FOR /R C:\hello\ %%G IN (*.txt) DO "c:\Program Files\7-Zip\7z.exe" a %%G.zip %%G && del %%G

Note that you cannot do this directly in the prompt, you must save it as a .bat file. It is of course also possible to allow the user to specify the paths and extensions with command line like this:

FOR /R %1 %%G IN (%2) DO "c:\Program Files\7-Zip\7z.exe" a %%G.zip %%G && del %%G

More information about FOR and other windows command line commands can be found here: http://ss64.com/nt/

This would then be run with:

test.bat C:\Hello\ *.txt

EDIT: This obviously requires you to have 7-Zip installed but it's pretty obvious where to change the code if you want to use some other zipper. Also keep in mind to always be Extremely careful when experimenting with scripts such as this. One small mistake could have it delete a lot of files, so you should always test it on a copy of the file system until you are absolutely sure it works.

MatsT
On my planet, Perl has been running well on Windows for many years.
mobrule
So, say I create a .bat file, content of the second one to specify the file extensions. How would I run that?
Scott
You would run it with "test.bat c:\hello\ txt". Alternatively you could replace the *.%2 in the batfile with simply %2 to let you specify any wildcards.@mobrule: Let me rephrase: It does run natively, but only if you install a Perl interpreter like ActivePerl on your system. It is useful for many purposes, but it seems like overkill here.
MatsT
+2  A: 

FORFILES is included with Windows and may be more applicable than FOR to what you're trying to do:

FORFILES [/P pathname] [/M searchmask] [/S] [/C command] [/D [+ | -] {MM/dd/yyyy | dd}]

Description: Selects a file (or set of files) and executes a command on that file. This is helpful for batch jobs.

Parameter List:

/P    pathname      Indicates the path to start searching.
                    The default folder is the current working
                    directory (.).

/M    searchmask    Searches files according to a searchmask.
                    The default searchmask is '*' .

/S                  Instructs forfiles to recurse into
                    subdirectories. Like "DIR /S".

/C    command       Indicates the command to execute for each file.
                    Command strings should be wrapped in double
                    quotes.

                    The default command is "cmd /c echo @file".

                    The following variables can be used in the
                    command string:
                    @file    - returns the name of the file.
                    @fname   - returns the file name without
                               extension.
                    @ext     - returns only the extension of the
                               file.
                    @path    - returns the full path of the file.
                    @relpath - returns the relative path of the
                               file.
                    @isdir   - returns "TRUE" if a file type is
                               a directory, and "FALSE" for files.
                    @fsize   - returns the size of the file in
                               bytes.
                    @fdate   - returns the last modified date of the
                               file.
                    @ftime   - returns the last modified time of the
                               file.

                    To include special characters in the command
                    line, use the hexadecimal code for the character
                    in 0xHH format (ex. 0x09 for tab). Internal
                    CMD.exe commands should be preceded with
                    "cmd /c".

/D    date          Selects files with a last modified date greater
                    than or equal to (+), or less than or equal to
                    (-), the specified date using the
                    "MM/dd/yyyy" format; or selects files with a
                    last modified date greater than or equal to (+)
                    the current date plus "dd" days, or less than or
                    equal to (-) the current date minus "dd" days. A
                    valid "dd" number of days can be any number in
                    the range of 0 - 32768.
                    "+" is taken as default sign if not specified.
William Leara
+2  A: 

Below one way I would do it in AutoIt since you asked. Replace the MsgBox line with whatever code you need to do whatever it is your wanting to do. AutoIt is fun stuff!

#include <File.au3>

archiveDir(InputBox("Path","Enter your start path."))

Func archiveDir($rootDirectory)
    $aFiles = _FileListToArray($rootDirectory)

    For $i = 1 To UBound($aFiles) - 1
        If StringInStr(FileGetAttrib($aFiles[$i]),"D") Then archiveDir($rootDirectory & $aFiles[$i] & "\")
        MsgBox(0,"This would be your archive step!",'"Archiving" ' & $rootDirectory & $aFiles[$i])
    Next
EndFunc
Copas