#!/usr/bin/perl # tk2compare.pl - A platform independent file comparer # # alotlikeyesterday@gmail.com # # version 0.4 # # future: more key bindings, rewrite compare algorithm # use strict; use Tk; use Tk::FileSelect; use Tk::DialogBox; #use Tk::Scollbar; #for perl2exe compilation use File::Compare; use Cwd; my $getfile1; my $getfile2; #remove the windows DOS shell window, comment when developing BEGIN { if ($^O eq 'MSWin32') { require Win32::Console; Win32::Console::Free(); } } #Main Definition my $main = MainWindow->new; $main->title("Tk2compare"); #Main Menu Bar definition my $menu_bar = $main->Frame()->pack(-side => 'top', -fill => 'x'); #Define File menu my $file = $menu_bar->Menubutton(-text => 'File', -activebackground => 'blue', -activeforeground => 'white')->pack(-side => 'left'); $file->command(-label => "Save A", -command => \&save_fileA); $file->command(-label => "Save B", -command => \&save_fileB); $file->command(-label => "Quit", -command => \&fini); #Define Help menu my $help_mb = $menu_bar->Menubutton(-text => 'Help', -activebackground => 'blue', -activeforeground => 'white')->pack(-side => 'left');$help_mb->command(-label => 'Help', -command => \&OnHelp); $help_mb->command(-label => 'About', -command => \&OnAbout); #$main->Label(-text => 'Compare Files!')->pack(-pady=>5); $main->title("Tk2compare"); #File Selections my $frameA = $main->Frame( -borderwidth=>3,)->pack(-side=>'top',-fill=>'x'); my $frame1 = $frameA->Frame( -borderwidth=>3,)->pack(-side=>'left',-fill=>'x'); my $textbox1 = $frame1->Entry(-width=>30, -background=>'white')->pack(-side=>'left',-pady=>3,-padx =>5); my $file1 = $frame1->Button(-text => 'File A', -command => sub{get_fileA()})->pack(-side=>'left'); my $save1 = $frame1->Button(-text => 'Save A', -command => sub{save_fileA()})->pack(-side=>'left',-padx =>5); my $frame2 = $frameA->Frame( -borderwidth=>3,)->pack(-side=>'right',-fill=>'x'); my $textbox2 = $frame2->Entry(-width=>30, -background=>'white')->pack(-side=>'right',-pady=>3,-padx =>5); my $file2 = $frame2->Button(-text => 'File B', -command => sub{get_fileB()})->pack(-side=>'left'); my $save2 = $frame2->Button(-text => 'Save B', -command => sub{save_fileB()})->pack(-side=>'left',-padx =>5); #Execute buttons and Status window $frameA->Button(-text => 'Compare!', -command => sub{compare_files()})->pack(-side=>'left',-pady => 3,-padx =>20); $frameA->Button(-text => 'Return all Rows', -command => sub{return_rows()})->pack(-side=>'right',-pady=>3,-padx =>25); my $status = $frameA->Entry(-width=>17, -background=>'white')->pack(-side=>'right',-pady=>3,-padx =>0); #text output boxes my $frameB = $main->Frame( -borderwidth=>3,)->pack(-side=>'bottom',-fill=>'x'); my $frame3 = $frameB->Frame( -borderwidth=>3,)->pack(-side=>'left',-fill=>'x'); my $text1 = $frame3->Scrolled('Text',-scrollbars => 'osoe',wrap=>'none'); $text1->configure(-background=>'white',-width => 60, -height => 40); $text1->pack(-side=>'left'); my $frame4 = $frameB->Frame( -borderwidth=>3,)->pack(-side=>'right',-fill=>'x'); my $text2 = $frame4->Scrolled('Text',-scrollbars => 'osoe',wrap=>'none'); $text2->configure(-background=>'white',-width => 60, -height => 40); $text2->pack(-side=>'right'); $textbox1->bind('' => sub{compare_files()}); MainLoop; sub get_fileA { my $fs = $main->getOpenFile; my $getfile1 = $fs; $textbox1->configure(-text => $getfile1); } sub get_fileB { my $fs = $main->getOpenFile; my $getfile2 = $fs; $textbox2->configure(-text => $getfile2); } sub compare_files { $text1->delete('1.0', 'end'); #clear the text boxes $text2->delete('1.0', 'end'); my $dat1 = $textbox1->get; my $dat2 = $textbox2->get; if (length($dat1) <= 1 || length($dat2) <=1 ) {print "file is null\n"; &nofile; return;} if (-e $dat1 && -e $dat2) { $getfile1 = $dat1; $getfile2 = $dat2; } else { &fileDNE; } if (-d $dat1 && -d $dat1) { #directories compare_dir_A($getfile1); compare_dir_B($getfile2); return; } if ($getfile1|$getfile2 !~ /./g ) { &nofile; return;} $text1->delete('1.0', 'end'); #clear the text boxes $text2->delete('1.0', 'end'); if (compare($getfile1,$getfile2) == 0) { $status->configure(-text => "Files are equal"); } else { $status->configure(-text => "Files are not equal"); &compare_detail_A; } } sub compare_detail_A { my %compare = (); open (F1, $getfile2) or die "$!"; while(){ chomp; $compare{$_}++; } close(F1); my $line_num = 0; open (F2, $getfile1) or die "$!"; while(){ $line_num++; chomp; $text1->insert('end', "$line_num $_\n") unless (exists($compare{$_})); } close(F2); &compare_detail_B; } sub compare_detail_B { my %compare = (); open (F1, $getfile1) or die "$!"; while(){ chomp; $compare{$_}++; } close(F1); my $line_num = 0; open (F2, $getfile2) or die "$!"; while(){ $line_num++; chomp; $text2->insert('end', "$line_num $_\n") unless (exists($compare{$_})); } close(F2); } sub return_rows { $text1->delete('1.0', 'end'); #clear the text boxes $text2->delete('1.0', 'end'); my $dat1 = $textbox1->get; my $dat2 = $textbox2->get; if (length($dat1) <= 1 || length($dat2) <=1 ) {print "file is null\n"; &nofile; return;} if (-e $dat1 && -e $dat2) { $getfile1 = $dat1; $getfile2 = $dat2; } else { &fileDNE; } if (-d $dat1 && -d $dat2) { #directories list_dir_A($getfile1); list_dir_B($getfile2); return; } if ($getfile1|$getfile2 !~ /./g ) { &nofile; return;} $text1->delete('1.0', 'end'); #clear the text boxes $text2->delete('1.0', 'end'); if (compare($getfile1,$getfile2) == 0) { $status->configure(-text => "Files are equal"); } else { $status->configure(-text => "Files are not equal"); } my $line_num = 0; open (F1, $getfile1) or die "$!"; while(){ chomp; # $line_num++; #with line #'s # $text1->insert('end', "$line_num $_\n"); $text1->insert('end', "$_\n"); #without line #'s } close(F1); my $line_num = 0; open (F2, $getfile2) or die "$!"; while(){ chomp; # $line_num++; #with line #'s # $text2->insert('end', "$line_num $_\n"); $text2->insert('end', "$_\n"); #without line #'s } close(F2); } sub list_dir_A { my $dir = shift; opendir(D1, $dir); my @f = readdir(D1); closedir(D1); foreach my $file (sort @f) { # my $filename = $dir . '/' . $file; #gives the full path my $filename = $file; #gives the file only if ($file eq '.' || $file eq '..') { } elsif (-d $filename) { $filename = $filename . '/'; $text1->insert('end', "$filename\n"); #print dir name } else { $text1->insert('end', "$filename\n"); } } } sub list_dir_B { my $dir = shift; opendir(D2, $dir); my @f = readdir(D2); closedir(D2); foreach my $file (sort @f) { # my $filename = $dir . '/' . $file; #gives the full path my $filename = $file; #gives the file only if ($file eq '.' || $file eq '..') { } elsif (-d $filename) { $filename = $filename . '/'; $text2->insert('end', "$filename\n"); #print dir name } else { $text2->insert('end', "$filename\n"); } } } sub compare_dir_A { my %compare_dir = (); opendir(D3, $getfile2) or die "$!"; my @dirlist = readdir(D3); closedir(D3); foreach my $t (sort @dirlist) { chomp; $compare_dir{$t}++; } my $line_num = 0; opendir(D4, $getfile1) or die "$!"; my @dirlist = readdir(D4); closedir(D4); foreach my $t (sort @dirlist) { $line_num++; chomp; $text1->insert('end', "$line_num $t\n") unless (exists($compare_dir{$t})); } } sub compare_dir_B { my %compare_dir = (); opendir(D5, $getfile1) or die "$!"; my @dirlist = readdir(D5); closedir(D5); foreach my $t (sort @dirlist) { chomp; $compare_dir{$t}++; } my $line_num = 0; opendir(D6, $getfile2) or die "$!"; my @dirlist = readdir(D6); closedir(D6); foreach my $t (sort @dirlist) { $line_num++; chomp; $text2->insert('end', "$line_num $t\n") unless (exists($compare_dir{$t})); } } sub save_fileA { my $savefileA = $main->getSaveFile; if (length($savefileA) <= 1) { return;} #if hit cancel $textbox1->configure(-text => $savefileA); my $getfile1 = $textbox1->get; if (length($getfile1) <= 1) {print "file is null\n"; &nofile; return;} my $savefile1 = $getfile1; #. '_tk2c'; my $data = $text1->get(0.1, 'end'); if (length($data) <= 1) {print "data is null\n"; &nodata; return;} open(FH1, ">$savefile1"); print FH1 $data; close(FH1); print "Saved file A to $savefile1\n"; } sub save_fileB { my $savefileB = $main->getSaveFile; if (length($savefileB) <= 1) { return;} #if hit cancel $textbox2->configure(-text => $savefileB); my $getfile2 = $textbox2->get; if (length($getfile2) <= 1) {print "file is null\n"; &nofile; return;} my $savefile2 = $getfile2; #. '_tk2c'; my $data = $text2->get(0.1, 'end'); if (length($data) <= 1) {print "data is null\n"; &nodata; return;} open(FH2, ">$savefile2"); print FH2 $data; close(FH2); print "Saved file B to $savefile2\n"; } sub OnAbout { my $about = $main->DialogBox( -title=>"About Tk2Compare", -buttons=>["OK"] ); $about->add('Label', -anchor => 'w', -justify => 'left', -text => qq( Tk2compare.pl Version 1.0 June 2005 This is a simple project that compares two text files. The code is written in Perl and uses the Tk package. You are free to modify, redistribute or otherwise change the program as you see fit. Drop me a line if you find Tk2compare useful. alotlikeyesterday\@gmail.com ) )->pack; $about->Show(); } sub OnHelp { my $about = $main->DialogBox( -title=>"Tk2Compare Instructions", -buttons=>["OK"] ); $about->add('Label', -anchor => 'w', -justify => 'left', -text => qq( 1\) Select files by clicking the "File A" and "File B" buttons at the top. The selection will be placed in the entry box. Or simply type the location of the file/directory in the entry box. 2\) Select "Compare!" to compare the two files. The left textbox produces output which contains the lines of File A which are NOT in File B. Conversely, the right textbox contains lines of File B which are NOT found in File A. 3\) Select "Return all Rows" to print the entire contents of the files to the text area 4\) Many more text options can be accessed by right clicking in the text area including word-wrap and search functions. ) )->pack; $about->Show(); } sub nofile { my $nofile = $main->DialogBox( -title=>"The files are not defined", -buttons=>["OK"] ); $nofile->add('Label', -anchor => 'w', -justify => 'left', -text => qq( The files are not defined! Define files by selecting the "File A" and "File B" buttons on the toolbar. ) )->pack; $nofile->Show(); } sub fileDNE { my $fileDNE = $main->DialogBox( -title=>"The files DNE", -buttons=>["OK"] ); $fileDNE->add('Label', -anchor => 'w', -justify => 'left', -text => qq( One or both of the files do not exist. Check the file and try again. ) )->pack; $fileDNE->Show(); } sub nodata { my $nodata = $main->DialogBox( -title=>"No data to write", -buttons=>["OK"] ); $nodata->add('Label', -anchor => 'w', -justify => 'left', -text => qq( There is no data to write, please load a file, or enter text in the text area and try to save again. ) )->pack; $nodata->Show(); } sub fini { exit; }