views:

42

answers:

3

I have a script that I'm using to remove duplicate Calendar entries. The root mail folder contains folders with each folder being firstname_lastname, then beneath each other is /Calendar/#msgs/.

As of now, I'm running script manually by going to the users' folder and starting the script /Users/Documents/duplicates/dups.pl . --killdups`

Is there a way that I could easily have it loops through all the users mail folders and look in the respective /Calendar/#msgs/ folder and run the script?

A: 

Pass in the folders it should look at on the command line. The arguments will be in @ARGV, you just loop over it.

Chas. Owens
How do I pass in the folders? There are about 400 folders, so to manually do this will take some time.
Aaron
@Aaron: programmatically of course. `*` is a wonderful invention in the shell.
Ether
@Aaron If it should always run against all of the folders, then have it use a [`glob`](http://perldoc.perl.org/functions/glob.html) like Ether suggests.
Chas. Owens
A: 

Edit: Maybe you prefer an elegant Perl solution ?

#!/usr/bin/perl -w
# CC-by Cedric 'levif' Le Dillau.

use File::Find;

@ARGV = qw(.) unless @ARGV;
find sub { apply_to_folder($File::Find::name) if -d }, @ARGV;

sub apply_to_folder {
    my $folder = shift;
    printf "folder: %s\n", $folder;
}

Then, yourapply_to_folder() function can be whatever you want.

Note that replacing -d by -f or -f && -x can change the filtering feature. (help can be found with perldoc -f -X)

Older proposition was:

Try using:

$ find "/Calendar/#msgs/" -type d -exec dups.pl "{}" --killdups \;

Or perl's opendir()/readdir() functions:

$ perldoc -f opendir
levif
I was thinking find might work. Do I use /#msgs in place of /myfolder?
Aaron
@Aaron: yes, so I edited the answer. Sorry I didn't found how to copy/paste on my iPhone ;)
levif
@Aaron: however, having a `#` in file or folder name is not really a good idea. You'll see ! :)
levif
Haha thanks, well unfortunately its just how the mail server works. Do you think this will work? maybe :-/
Aaron
@Aaron: you'll just have to be careful for scripting as `#` is the comment start. It works fine as parameter.
levif
+1  A: 

There are a couple ways you can go with this, depending on what you want to do.

First, you can make your script search every folder under it's starting directory. You don't specify anything on the command line.

 use File::Spec::Functions qw(catfile);

 my @users = glob( '/Users/*' );
 foreach my $user ( @users ) {   # $user looks like /Users/Buster
      my $calendar_dir = catfile( $user, 'Calendar', '#msgs' );
      ...
      }

You could also use opendir to get the list of users so you get back one directory at a time:

 opendir my $dh, '/Users' or die ...;
 while( my $user = readdir $dh ) {
     next if $user =~ /^\.\.?\z/; # and anything else you want to skip
     ... # do the cool stuff
     }

Second, you can make it search selected folders. Suppose that you are in your home directory. To kill the duplicates for the particular users, you'd call your script with those user's names:

 dups.pl --killdups Buster Mimi Roscoe 

To go through all users, maybe something like this (it almost looks like you are on MacOS X, but not quite, so I'm not sure which path you need), using a command-line glob:

 dups.pl --killdups /Users/*

The solution looks similar, but you take the users from @ARGV instead of using a glob:

 foreach my $user ( @ARGV ) {
      ...
      }

That should be enough to get you started. You'll have to integrate this with the rest of your script and fix up the paths in each case to be what you need, but that's just simple string manipulation (or even simpler than that with File::Spec.

brian d foy