Every night, I have a cron job run which backs up critical directories (I maintain a list) such as my school files, Pidgin logs, IRC logs, and my F-Spot database. These files are then tarred, gzipped, encrypted using des3, and then committed to a remote private Subversion (SVN) repository. This way, I lose only 24 hours, at most. Using SVN means that I can recover a snapshot from any given day. After I clean up the code for that Bash script, I'll be posting that as well.

The point of that story was to lead into my next one: I recently realized that importing archived Pidgin logs into a current install was very time-consuming. This is due to the directory structure for logs: {code lang="text" numbers=false} ~/.purple/logs/\\{protocol\\}/\\{nickname\\}/\\{buddynick\\}/\\{logfiles\\} {/code}

Looking at that line, it's not obvious [i]why[/i] that makes it so tedious, but look at the directory tree of a working Pidgin install and you'll see what I mean. Noticing this, I whipped up a short Perl script to merge any two working directories. It's pretty straight-forward and obvious to anyone with any programming knowledge, but not everyone can be so fortunate. Here's the code: {code lang="perl"}{literal}

!/usr/bin/perl

file name: dir_merger.pl

author: Evan Charlton

description:

Given a input and output directories, it will merge all the

contents from the input in with the output, recreating any

missing directory structures in the process.

##################################################################

use strict; use warnings;

our $from_dir; our $dest_dir;

sub process_dir { my $current_dir = shift; my $cmd = "ls -l "$current_dir""; my @contents = $cmd; my $out = $current_dir; $out =~ s/$fromdir/$destdir/; if(!(-e $out)){ # the directory does not exists so we must create it $cmd = "mkdir $out"; my @res = $cmd; my $temp = join( " ", @res ); if($temp =~ /cannot/){ # Uh-oh! We couldn't create the directory! print "Error! $out could not be created!\\ntTerminating...n"; exit 0; } } foreach (@contents){ if(/^d[a-zs0-9-]+[0-9]+:[0-9]+ (.*)$/){ # We have a directory; recurse into it processdir( $currentdir.$1."/" ); } elsif(/^[a-zs0-9-]+[0-9]+:[0-9]+ (.*)$/){ # file found; we need to copy it to its new home printf "%s%s -> %s%sn", $current_dir, $1, $out, $1; $cmd = "cp "$current_dir$1" "$out$1""; print $cmd; } } }

if(@ARGV == 2){ if($ARGV[0] ne $ARGV[1]){ if(-e $ARGV[0]){ if(-e $ARGV[1]){ $from_dir = $ARGV[0]; $dest_dir = $ARGV[1]; # make sure they both have trailing slashes $from_dir = (($ARGV[0] =~ //$/) ? $ARGV[0] : $ARGV[0]."/"); $dest_dir = (($ARGV[1] =~ //$/) ? $ARGV[1] : $ARGV[1]."/"); printf "%sn%sn", $fromdir, $destdir; exit 0; processdir( $fromdir ); } else{ printf "Could not open "%s"\\ntDoes it exist?n", $ARGV[1]; } } else{ printf "Could not open "%s"\\ntDoes it exist?n", $ARGV[0]; } } else{ print "The input and output directories can not be the same!\\n"; } } else{ print "Usage: $0 path/with/old/files/ path/for/new/files/\\n"; }

exit 0;

END

=head1 NAME

dir_merger.pl -- Parses mobile properties out of basic mobiles.

=head1 DESCRIPTION

Given a directory of Gaim/Pidgin logs, this will loop through and copy all the logs for each user to the correct new directory.

=head1 OPTIONS

No options. Must be used as such:

./dir_merger path/to/old/dir/ path/to/new/dir/

Note that the trailing slashes are optional, though recommended

=head1 AUTHOR

Evan Charlton evan@evancharlton.com

=cut {/literal}{/code}

Note that this is only Linux-compatible, due to the parsing on the "ls -l". I suppose it might run under Cygwin, but I haven't tested it (nor do I plan to; sorry).

Example usage: ./dir_merger.pl ~/.gaim/logs/ ~/.purple/logs/ This would move any logs that were left in an old Gaim install to the new Pidgin install.

Don't forget that dir_merger.pl must be executable: chmod +x dir_merger.pl

Final note: this script is not Pidgin or Gaim specific; it can merge any two directories.