dirdiff is a simple script to show a files diff for two directories. Similar to the real 'diff', things in directory a are prefixed with a '<'. Things in directory b are prefixed with a '>' and things in both directories are prefixed with a '='. The prefix may be removed with the --plain option. Options exist to display results by themselves or in combination. The default setting is to display files in a, not in b, and files in b, not in a. To add the intersection of a and b, use the --inter option. Note that the default entry for the path2 is '.'.No doubt there is a better unix solution, but I don't live there so to speak!
#!/usr/bin/perl # dirdiff.pl -- files diff for two directories. use strict; use warnings; use diagnostics; use File::Find qw(find); use Getopt::Long; use Pod::Usage; use Cwd qw(abs_path); use Sort::Naturally; our $VERSION = '0.05'; my @opt_exts; GetOptions( 'debug=i' => \( my $debug = 0 ), 'help|?' => \( my $opt_help ), 'man' => \( my $opt_man ), 'version' => \( my $opt_version ), 'aonly' => \( my $opt_aonly ), 'bonly' => \( my $opt_bonly ), 'inter' => \( my $opt_inter ), 'jonly' => \( my $opt_jonly ), 'plain' => \( my $opt_plain ), 'order' => \( my $opt_order ), 'ext=s' => \@opt_exts, ) or pod2usage(2); if ($opt_version) { print "$0 vrs. $VERSION\n"; exit; } pod2usage(1) if $opt_help; pod2usage( -verbose => 2 ) if $opt_man; pod2usage("$0: No paths given.") unless @ARGV; @opt_exts = split ( /,/, join ( ',', @opt_exts ) ) if @opt_exts; push ( @ARGV, '.' ); my @dir1 = scandir( $ARGV[0], @opt_exts ); my @dir2 = scandir( $ARGV[1], @opt_exts ); if ( not( $opt_bonly or $opt_jonly ) ) { print_diff( '<', abs_path( $ARGV[0] ), diff( \@dir1, \@dir2 ) ); } if ( not( $opt_aonly or $opt_jonly ) ) { print_diff( '>', abs_path( $ARGV[1] ), diff( \@dir2, \@dir1 ) ); } if ( $opt_inter or $opt_jonly ) { print_diff( '=', '', isect( \@dir1, \@dir2 ) ); } sub print_diff { my ( $decor, $dir, @filename ) = @_; my $prefix = ''; $prefix .= "$decor " if $opt_plain; $prefix .= "$dir" if defined $dir and length $dir; # awkward :-( print map "$prefix$_\n", $opt_order ? nsort(@filename) : @filename +; } sub scandir { my ( $dir, @extensions ) = @_; my @dirlist; find( sub { return if /^\.$/ or /^\.\.$/; if (@extensions) { return unless matched( $_, @extensions ); } push ( @dirlist, substr( $File::Find::name, index( $File::Find::name, ' +/' ) ) ); }, $dir ); return @dirlist; } sub matched { my $pat = shift; my @pats = @_; return grep $pat =~ /$_$/, @pats; } sub diff { my $a = shift; my $b = shift; my %seen; my @aonly; @seen{@$b} = (); for (@$a) { push ( @aonly, $_ ) unless exists $seen{$_}; } return @aonly; } sub isect { my $a = shift; my $b = shift; my %union; my %isect; for ( @$a, @$b ) { $union{$_}++ && $isect{$_}++; } return keys %isect; } __END__ =head1 NAME dirdiff - files diff for two directories. =head1 SYNOPSIS dirdiff [options] path1 [path2] Options: --debug set debug level, default is off --help brief help message --man full documentation --version version number --aonly files in a not in b only --bonly files in b not in a only --inter files in a and b --jonly files in a and b only --plain display result with out prefix; '>', '<' or '=' --order sorted display of result --ext allowed file extensions Switches that don't define a value can be done in long or short form. eg: dirdiff --man dirdiff -m =head1 OPTIONS =over 8 =item B<--debug> Display debug information as program is executed. Control is set by le +vel of the value passed on the command line. Default value is off (debug == 0). =item B<--help> Print a brief help message and exit. =item B<--man> Print the manual page (full documentation) and exit. =item B<--version> Print the version number and exit. =item B<--aonly> Print files in directory a not in directory b. =item B<--bonly> Print files in directory b not in directory a. =item B<--inter> Print files jointly in both directories (intersection of directory a a +nd directory b). =item B<--jonly> Print files jointly in both directories only. =item B<--plain> Print results free of decoration, i.e. no '>', '<' or '='. =item B<--order> Sort level. Defaults to the sort of no sort. Using this options will sort the results in ascending order. =item B<--ext> Allows for specification of file extension to limit result. May be use +d multiple times or with a comma separated list. =back =head1 DESCRIPTION dirdiff is a simple script to show a files diff for two directories. S +imilar to the real 'diff', things in directory a are prefixed with a '<'. Things in +directory b are prefixed with a '>' and things in both directories are prefixed wi +th a '='. The prefix may be removed with the --plain option. Options exist to displa +y results by themselves or in combination. The default setting is to display files +in a, not in b, and files in b, not in a. To add the intersection of a and b, us +e the --inter option. Note that the default entry for the path2 is '.'. =head1 AUTHOR Hugh S. Myers hsmyers@sdragons.com =head1 BUGS None that I know of. =head1 TODO 0. Edit POD. ONGOING. 1. Add some mechanism for wild card specification. DONE. 2. Add --stats to display date and size information with diff accordi +ngly. 3. Add --order to allow sorted output. DONE. =head1 UPDATES 1. Removed File::Spec::Functions in favor of Cwd, which has the virtu +re of working! 2. Added refactor ala Aristotle---thank you sir! 3. Added --ext to allow specifying extensions. 4. Added --order for sorted output. 5. Added use Sort::Naturally. 6. Aristotle refactors his refactor---thanks again! 7. Restored --order that my implementation of #6. stepped on! =cut
--hsm
"Never try to teach a pig to sing...it wastes your time and it annoys the pig."
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: A directory diff
by Aristotle (Chancellor) on Aug 25, 2004 at 21:40 UTC | |
by hsmyers (Canon) on Aug 26, 2004 at 12:55 UTC | |
by Aristotle (Chancellor) on Aug 26, 2004 at 22:27 UTC | |
by hsmyers (Canon) on Aug 27, 2004 at 14:29 UTC | |
|
Re: A directory diff
by belg4mit (Prior) on Aug 25, 2004 at 21:33 UTC | |
by hsmyers (Canon) on Aug 26, 2004 at 12:52 UTC | |
by belg4mit (Prior) on Aug 26, 2004 at 13:23 UTC | |
by hsmyers (Canon) on Aug 26, 2004 at 13:31 UTC | |
|
Re: A directory diff
by sgifford (Prior) on Aug 31, 2004 at 17:38 UTC | |
by hsmyers (Canon) on Sep 01, 2004 at 13:01 UTC | |
by BravoTwoZero (Scribe) on Dec 03, 2004 at 17:18 UTC | |
by hsmyers (Canon) on Dec 03, 2004 at 20:57 UTC |