Harry Putnam wrote:
I'm not sure what these errors are telling me.

The script is supposed to remove dups from .bash_history

Wouldn't it be simpler to set HISTCONTROL to ignoredups:

export HISTCONTROL=ignoredups

Or:

export HISTCONTROL=ignoreboth


but not operate on the last 12 lines... just reprinting them.

./uniqbh.pl
 Copying ./bash_history to ./bash_history-101809_020827
 Unlinking ./bash_history
Copying /tmp/lPlN3goGnI.tmp ./bash_history Operation "eq": no method found,
        left argument in overloaded package File::Temp,
        right argument has no overloaded magic at
 /usr/lib/perl5/5.8.8/File/Copy.pm line 76, <BASH_HISTORY> line 18151.

------- 8< snip ---------- 8< snip ---------- 8<snip ------- #!/usr/bin/perl

use strict;
use warnings;

# my $BashHistory = "$ENV{'HOME'}/.bash_history";
my $BashHistory = "./bash_history";
my $data = '';
my %data;
my $ext = '.tmp';
## Creat an honest to goodness random tmp file name
require File::Temp;
use File::Temp ();

Those two lines both do the same thing.  Pick *one*.


# [HP 101709_220324  Unlink is set to 1 by default .. that
# means it will be unlinked when the object goes out of scope
# so setting it to 0 means I have to delete (unlink) it manually my $tmpfile = new File::Temp( UNLINK => 0, SUFFIX => '.tmp' );

Usually written as:

my $tmpfile = File::Temp->new( UNLINK => 0, SUFFIX => '.tmp' );


open(TMPFILE,">$tmpfile") or die "Can't open $tmpfile: $!";

Why are you opening the file again? You already have a writable filehandle in $tmpfile.


## Keep this many lines from being processed, but do include them
## in the final file.
my $KeepLines = 12;
my $ProcessLines = (count_lines($BashHistory) - $KeepLines);

##### BEGIN Body ##### ##### ##### open(BASH_HISTORY,"<$BashHistory")or die "Can't open $BashHistory: $!";
while (<BASH_HISTORY>) {
    chomp;
  ## Process all but $KeepLines
  if($. <= $ProcessLines){
    ## finds unique input lines and prints them to a separate file
    if ($data{$_}++ == 0) {
      print TMPFILE $_ . "\n";

Why chomp the newlines off and then just add them back on again?


    }
  }elsif($. > $ProcessLines){
print TMPFILE $_ . "\n"; }
}

open my $BASH_HISTORY, '<', $BashHistory or die "Can't open $BashHistory: $!";
while ( <$BASH_HISTORY> ) {
    ## Process all but $KeepLines
    if ( $. <= $ProcessLines ) {
        ## finds unique input lines and prints them to a separate file
        next if $data{ $_ }++;
        }
    print $tmpfile $_;
    }


close(TMPFILE);

use File::Copy;

print "Copying $BashHistory to ".$BashHistory."-". PaddedDateStr()."\n"; copy( $BashHistory, $BashHistory . "-" . PaddedDateStr() )
                or die "Copy failed: $!";

print "Unlinking $BashHistory\n";
unlink $BashHistory;

unlink $BashHistory or die "unlink failed: $!";


print "Copying $tmpfile $BashHistory \n";
copy( $tmpfile, $BashHistory ) or die "Copy failed: $!";

print "Unlinking $tmpfile\n";
unlink $tmpfile;

unlink $tmpfile or die "unlink failed: $!";


##### BEGIN sub functions ##### ##### sub count_lines {
    my $file = shift;
    open my $fh, "<", $file
        or die "could not open $file:$!";
    my $lines = 0;
    $lines++ while <$fh>;
    return $lines;
}

perldoc -q "How do I count the number of lines in a file?"


sub PaddedDateStr {
my ($mon,$mday,$year,$hour,$min,$sec,$wday) = (localtime(time))[4,3,5,2,1,0,6];
# $year += 1900; ## prints 2005 $year -= 100; ## prints 05 (with %02d)

If you were writing this ten years ago you would now have a negative number in $year. If this is still in use one hundred years from now you will now have a three digit number in $year. Use modulus instead.


    $mon  += 1;
my  $PaddedDateStr = sprintf "%02d%02d%02d%s%02d%02d%02d", 
$mon,$mday,$year,"_",$hour,$min,$sec;
    return $PaddedDateStr;
}

Or just:

sub PaddedDateStr {
    my ( $sec, $min, $hour, $mday, $year ) = localtime;
return sprintf '%02d%02d%02d_%02d%02d%02d', $mon + 1, $mday, $year % 100, $hour, $min, $sec;
    }

But why are you using Month-Day-Year order? Your file names would sort better in Year-Month-Day order.

Or use the POSIX::strftime function:

use POSIX 'strftime';
sub PaddedDateStr {
    return strftime '%m%d%y_%H%M%S', localtime;
    }




This may work better for you:

#!/usr/bin/perl
use strict;
use warnings;

use Fcntl qw/ :seek :flock /;
use POSIX qw/ strftime /;
use File::Copy;

# my $BashHistory = "$ENV{HOME}/.bash_history";
my $BashHistory    = 'bash_history';
my $newBashHistory = "$BashHistory-" . strftime '%m%d%y_%H%M%S', localtime;
my $KeepLines      = 12;


print "Copying $BashHistory to $newBashHistory\n";
copy( $BashHistory, $newBashHistory ) or die "Copy failed: $!";


open my $FH, '+<:raw', $BashHistory or die "Cannot open '$BashHistory' $!";
flock $FH, LOCK_EX or die "Cannot flock '$BashHistory' $!";

my @lines = <$FH>;
my @keep = splice @lines, -$KeepLines;

my %unique = map { $_ => 1 } @keep;

seek $FH, 0, SEEK_SET or die "Cannot seek '$BashHistory' $!";
truncate $FH, 0 or die "Cannot truncate '$BashHistory' $!";

print $FH grep( !$unique{ $_ }++, @lines ), @keep;

close $FH or die "Cannot close '$BashHistory' $!";


__END__






John
--
The programmer is fighting against the two most
destructive forces in the universe: entropy and
human stupidity.               -- Damian Conway

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to