in reply to File synchronisation (for criticism)

(Hi to a fellow Cambridge person...)
Note that these are mostly style issues, aimed at readability.

You are doing a lot of checking of parameters. 2 ways I use to make this clearer (and 1 other comment) are :

  1. Use prototypes, e.g.
    sub CompareTrees($$\%\%)
    Perl will check that you are getting 2 scalars and 2 hashrefs and generate an error for you if not met. If the caller provides a hash, not a ref, Perl also generates the ref for you - DWIM.
  2. Count the parameters passed in. e.g.
    sub CompareTrees { @_ == 4 || warn "CompareTrees($srcPath,$destPath,\%srcTree, \%destTree)" && return undef; my ($sourcePath,$destPath,$sourceTree, $destTree) = @_;
    I think that is clearer and quicker to read and doesn't reduce reduce the usability.
  3. You are checking for errors within CompareTrees and then returning undef, only to die in the caller if you return the undef. If you are going to die anyway, you may as well do it where you find the error.
    sub CompareTrees { @_ == 4 || die "CompareTrees($srcPath,$destPath,\%srcTree,\%destTree)"; my ($sourcePath,$destPath,$sourceTree, $destTree) = @_;

    Personally, if I am checking in one place, I don't check in the other unless I am feeling paranoid, and try to throw the exception as close to the error as possible. This just makes the code flow more easily.
Config::IniFiles will do the Config file reading for you.
--
Brovnik