in reply to Create zip files for each sub-directory under a main directory

G'day mrd1019,

Welcome to the Monastery.

"I’m thinking a foreach loop would work?"

Did you try that? If so, what difficulties did you encounter? If not, then give it a go and, if you encounter difficulties, tell us what they are.

"I’m not 100% sure how to go about getting to my end goal."

Again, without knowing what your problem is, it's not really possible to offer a solution.

I'll take a complete guess that you don't know how to generate the "apxxxx.zip" filenames. For this, you'll probably want the sprintf function. Here's an example with printf (which uses the same formats as sprintf):

$ perl -e 'printf "ap%04d.zip\n", $_ for (0, 1, 234, 1335)' ap0000.zip ap0001.zip ap0234.zip ap1335.zip

— Ken

  • Comment on Re: Create zip files for each sub-directory under a main directory
  • Download Code

Replies are listed 'Best First'.
Re^2: Create zip files for each sub-directory under a main directory
by mrd1019 (Novice) on Nov 29, 2016 at 19:40 UTC

    So, I initially tried Stevieb's suggestion. It created the zip files, but there were no files inside the zip. So, I started playing. Again, I'm getting the zip files created, with the correct names, but there are no files inside the zips. Here is the latest attempt that I made at this:

    use strict; use warnings ‘all’; use File::Copy::Recursive; use Archive::Zip; use constant AZ_OK =>0; use File::Basename; use File::Find::Rule; my $mkvingestdir = “//nas/data/nonops/common/engine/ingest/sim/mkv”; my $mkvingestdest = “//nas/shared/group/test/mkv/ingest”; my @dirs = File::Find::Rule->directory() ->in($mkvingestdir); my @files; foreach my $dir (@dirs) { @files = glob "*.eap"; my $mkvingestzip = Archive::Zip->new(); foreach $_ (@files) { $mkvingestzip->addFile($_); } my $name = basename $dir; if ($mkvingestzip->writeToFileNamed("$mkvingestdest/${name}.zip") + != AZ_OK) { print "Error in archive creation\n"; next; } print "Archive created successfully!\n"; }
      foreach my $dir (@dirs) { @files = glob "*.eap"; my $mkvingestzip = Archive::Zip->new(); foreach $_ (@files) { $mkvingestzip->addFile($_); }

      I think that your problem here is that you are performing the glob in the $CWD which is not $dir and therefore it isn't matching. You could confirm this by adding diagnostic print statements like this:

      foreach my $dir (@dirs) { print "Now processing dir $dir\n"; @files = glob "*.eap"; my $mkvingestzip = Archive::Zip->new(); foreach $_ (@files) { print "Adding file $_\n"; $mkvingestzip->addFile($_); }

      You will likely see the "dir" diagnostics but no "file" ones. In that case you'll need either to chdir inside the outer loop or else prepend the path to the glob argument.

      Printing diagnostics like this is item number 2 on the Basic debugging checklist.

      You should check what's actually in @files. Not just for filenames but also whether they exist and (perhaps also) are of the expected size: see the built-in "File Test Operators".

      I suspect you probably want to glob "$dir/*.eap". With your posted code, you're only looking for "*.eap" in the current directory. Look for other places where you may be referencing the current directory instead of $dir.

      Two other minor points: (1) I wouldn't declare @files globally; (2) foreach and for are synonymous.

      Putting all those points together, instead of:

      my @files; foreach my $dir (@dirs) { @files = glob "*.eap"; ...

      I probably would have written something closer to:

      for my $dir (@dirs) { my @files = glob "$dir/*.eap"; ...

      For the inner loop, $_ is the default. Adding it the way you have (foreach $_ (@files) { ...) makes me, and quite possibly others, wonder if you perhaps had some other intention, e.g. a lexical 'my $_' (which should be avoided anyway - see below). One of these two forms would be more normal (and won't raise eyebrows):

      for (@files) { ...
      for my $file (@files) { ...

      [Use foreach, instead of for, if you want to. It's really just extra (and unnecessary) typing. As stated earlier, the two are synonymous.]

      Using a consistent style of indentation will make your code easier to read and less prone to errors. The choice of coding style is often a very personal one: choose whatever you want. See perlstyle if you want some tips on this.

      Finally, and only because I mentioned it passing above, lexical $_ should be avoided. Here's its history:

      — Ken

      As hippo and kcott have pointed out, I was using glob incorrectly.

      That's what I get for not fully following through to ensure everything did what it was supposed to ;)