Harry Putnam wrote:
"John W. Krahn" <jwkr...@shaw.ca> writes:

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

Yes of course.. I know and use HISTCONTROL like your second example.
This script was a way to keep up and expand somewhat, my tiny perl
skills. But also there have been occasions when I wanted to know how
many times I'd ran a command.  It can come up when coding and testing
as you go.  I just guessed at leaving 12.. it may need more like
20-26.
[...]

require File::Temp;
use File::Temp ();
Those two lines both do the same thing.  Pick *one*.

Thanks...
So I've heard else where in this thread.  It doesn't take much to
confuse me.. and the way the documentation of File::Temp was written
it appeared (to me)to be saying to use both.

Yes, it appears that the File::Temp documentation is ambiguous or outdated at some points.


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

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

Oh.. thanks.. I just took the example from perldoc near verbatim.
open(TMPFILE,">$tmpfile") or die "Can't open $tmpfile: $!";
Why are you opening the file again?  You already have a writable
filehandle in $tmpfile.

I didn't quite get that the file was opened in that first operation.

Yes, File::Temp->new() or File::Temp::tempfile() create and open a file for reading/writing and return the opened filehandle/file name. The object returned from the method File::Temp->new() can be used both as a filehandle or a file name, depending on context.


## 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?

I learned to be leery of including newlines and just automatically
chomp them.  I've had problems arise and had trouble tracking them
down, finally to find, it was induced by the presence of a new line.

I don't often know what all my `while' loop is going to do until I
start writing it. I often find that what I wanted to do, changes as I
go. So for me, chomping right off the reel, means I always know how to
treat the print action.

Maybe when I'm more confident of my perl skills I will know in advance
when chomping will be an unneeded extra move.

Yes, it is usually good practice to chomp() incoming file lines, it's just that sometimes it isn't. :-)


    }
  }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 $_;
    }

Haa, you turned it around, shortening it too... very nice.

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: $!";

Whoops, I should have caught that one... thanks.

[...]

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

Thanks for including the search sting too.  I `borrowed' that snip of
code in my script from an old post by Chas Owens here, but why is the
way described in perldoc (

     $lines = 0;
     open(FILE, $filename) or die "Can't open `$filename': $!";
     while (sysread FILE, $buffer, 4096) {
         $lines += ($buffer =~ tr/\n//);
     }
     close FILE;
)
 better?

It is usually more efficient, but not necessarily "better".   :-)


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.

Yup, I see that now..
    $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.

I never gave a moments thought to sorting.  Its just that I'm so used
to looking at strings like 101209_132140 and knowing at a quick glance
what the date is .

I may have to get used to year first, because that sorting thing could
be of some consequence when you've written a whole herd of them.

Or use the POSIX::strftime function:

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

Now that is a big help... I've fumbled around with localtime array
quite a bit a few times.  Finally writing that sub routine a yr or so
ago, and keeping it in a personal library to just read into a new
script when ever I needed a zero padded date string.

That POSIX module looks like just the ticket.


This may work better for you:
#!/usr/bin/perl

[...]

Oh, nice... many thanks for such a professional looking script.  The
truth is though I will need to study on this a while to get familiar
with what is going on there...And look up and study some of the
(unfamiliar to me) items introduced.

I envy your ability to just whip out stuff like this... thanks for
taking time to do it.

A nice piece of homework you've given me.

Part of my reason for even writing this script was to keep whatever
little skills I've finally acquired and maybe learn a bit too.
Working my way through your script will be good jump on that aspect.

One thing here, I'm considering completely ditching both File::Temp
and File::Copy

Can you tell me if there are good reasons to stick with File::Temp in
this situation?

A lot depends on things like file size, whether the file is on a local or remote file system, if functions like truncate() are supported on your system, etc.


 When I thought about it a bit after being prompted by
Jim G in this thread. I realized I didn't have a good reason to be
concerned about randomness or clobbering etc, with my new working
file.

I'm on a single user machine at home.  I'm thinking I could just write
to /tmp/BashHistoryDeDup.tmp with the `>' flag, overwriting on each
run and forget unlinking

That could be a security hole. Even though you have a single user machine it is always best practice to build security into your software from the beginning instead of trying to add it on later.


Again thanks for the nice piece to study on.



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