tags:

views:

262

answers:

3

Hi,

I am zipping directory which has sub directories and there are few files which I don't need (in those sub dirs), can you modify the following script so it would skip certain files I want?

Can pay up to $20 to PayPal for your hard work :-)

procedure DoProgress(Sender: TObject; Position, Total: Integer);
procedure DoCompressFile(Sender: TObject; const Filename: string);

....

procedure TJvZLibMultipleMainForm.DoCompressFile(Sender:TObject;const Filename:string);
begin
  lblFilename.Caption := Filename;
  Update;
end;

    procedure TJvZLibMultipleMainForm.btnCompressClick(Sender: TObject);
var
  z : TJvZlibMultiple;
begin
  ForceDirectories(ExtractFilePath(edFilename.Text));
  z := TJvZlibMultiple.Create(nil);
  Screen.Cursor := crHourGlass;
  try
    lblFilename.Caption := '';
    pbProgress.Position := 0;
    z.OnProgress := DoProgress;
    z.OnCompressingFile := DoCompressFile;
    z.CompressDirectory(edSrcFolder.Text,true,edFilename.Text);
  finally
    z.Free;
    Screen.Cursor := crDefault;
  end;
  pbProgress.Position := 0;
  lblFilename.Caption := 'Ready';
end;


procedure TJvZLibMultipleMainForm.DoProgress(Sender: TObject; Position, Total: Integer);
begin
  pbProgress.Max := Total;
  pbProgress.Position := Position;
  Update;
end;
+2  A: 

You must walk to directory and any subdirectories and search for all file names. Any file name or file name extension compare with 'do not compress' list, if file name not on the that list add it to zip file with TJvZlibMultiple.AddFile.

GJ
+6  A: 

In the absence of real documentation for the JVCL TJvZlibMultiple component, a review of the source code of JVCL's showed that there are no settings at the level of TJvZlibMultiple that can be used to preventing the systematic zipping of _*all*_ the files (!) in the directory. It appears it is not even possible to pass a file filter (as say "*.PAS").

The TJvZlibMultiple object does include some notification hooks, such as OnCompressingFile, which is called just before compressing a file, but and the driving logic does not test any return from the handler (which is in fact a procedure...), and therefore we cannot use this device to signify that the file should be skept.

Given this situation you are left with three main options:

  • A suggested by GJ, you can work at a lower level and feed the files to be compressed individually
    Pseudo code:
       -manually initializing the archive 
       -iterate for each file in the directory (ies) (recursively if needed)
          -decide if file is to be added
          -adding it individually with the TJvZlibMultiple.AddFile() procedure
        -close the archive
        
    In a nutshell, "no fun" :-( This in fact will require to derive a class from TJvZlibMultiple, because some procedures are protected, and some others rely on some private/protected variables to be intialized...
  • Built a custom version of JVCL, specifically changes to the TJvZlibMultiple.pas file (if you do this well, that could be submitted back into the main trunk of JVCL project)

    Essentially the Notification events, in particular OnCompressingFile would 
    return a value, either by beying a true function (or a procedure with side
    effect, for backward compatibilty), and such return would be tested by the
    CompressDirectory logic, to skip files (and possibly other features such as
    'abort', 'use an alternate file', whatever...).
  • pre-process the directory(ies)

    by [temporarilly] moving the undesired files elsewhere.
    (and then calling the unmodified CompressDirectory(), 
    and then moving the files back...)

Effectively none of these solution is very appealing. IMHO the middle one is probably the quickest, but your code would then be branched out form the official JVCL, unless you make the effort of submitting the mods to the open source project)

A fourth choice is maybe to use an alternative ZIP library, and to somehow integrate it with your UI.

Have fun ;-)

mjv
+1 for detailed answer.
Wodzu
Is it possible to modify script so it would scan for specific files in all dirs and "move it" or delete it , and then zip?
Tom
@Tom: that would be equivalent to mjv's option 3. That presents a number of problems, among them the amount of time and drive space used in making the copy. It's not a hard option to implement, but mjv's suggested solution is a much better design.
Argalatyr
Thank you, Argalatyr for the kind words on my preferred suggestion. The option 3 (scanning the dirs and moving _or deleting_ the undesired files) would not consume extra disk space, nor would it be slow (relative to zipping time). The "move" of a file effectively moves the directory "meta" info for that file, but leaves the file itself in-situ (i.e. copies the file name, date, location, permissins flags etc. to other directory file, then delete it from orginal directory file.) Indeed, when deleting, it would be _saving_ disk space.
mjv
@mjv: you are correct. I was thinking of a different approach (copying files to be compressed) when I wrote that comment - thanks for pointing that out.
Argalatyr
It's not possible to move files as they are used atm.
Tom
+1  A: 

How about zipping the entire directory, and then removing those files from the ZIP? Certainly not efficient, but it gets the job done.

I use TZipMaster, and have done something similar with it. It's a visual component, but can also be used as a runtime component. It's open-source.

Mick