Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Rolling variable

by artperl (Acolyte)
on Jul 30, 2015 at 13:35 UTC ( [id://1136865]=perlquestion: print w/replies, xml ) Need Help??

artperl has asked for the wisdom of the Perl Monks concerning the following question:

Dear Perl monks, I would like to seek recommendation on what could be a good solution here... I would like to monitor file count in a specific directory & record the count every hour. I would need to keep that counts somewhere for another calculation but I would like to keep only the last 8 counts, meaning throw away the oldest data & just keep the last 8 records. How can I effectively do this in perl? Thanks much!...

Replies are listed 'Best First'.
Re: Rolling variable
by stevieb (Canon) on Jul 30, 2015 at 13:59 UTC

    You can use Tie::File to store your data in a file, and use push and shift per Ratazong's suggestion on the array which modifies the file live-time:

    use Tie::File; tie my @file, 'Tie::File', 'file.txt' or die $!; shift @file if @file == 8; ... push @file, 'new data'; ... untie @file;

    Then, use cron to run your script every hour, and for any other external processing, just pull the data out of the 'file.txt' file.

    -stevieb

Re: Rolling variable
by Ratazong (Monsignor) on Jul 30, 2015 at 13:43 UTC

    Hi artperl

    For 8 integer-values an array seems to be the easiest (and efficient enough). Please check push for appending a value at the end and shift to remove the first element.

    HTH, Rata

Re: Rolling variable
by fishmonger (Chaplain) on Jul 30, 2015 at 14:02 UTC

    I would need to keep that counts somewhere for another calculation but I would like to keep only the last 8 counts

    If the script is being executed each hour (presumably via a cron job) and you need to retain/use the array from the prior run, then you might want to look at using the Storable module to store/retrieve the array.

    Update:
    Just in case you weren't sure what I was suggesting, here's a short test script example.

    use strict; use warnings; use Storable qw(store retrieve); my @cnt = -e 'file_count' ? @{ retrieve('file_count') } : ('') x 8; my $fcount; $fcount++ for glob('*'); unshift @cnt}, $fcount; pop @cnt; store(\@cnt, 'file_count');

    Edit: changed the array reference $cnt_aref to a plain array @cnt

Re: Rolling variable (Update:prime the counts file first!)
by BrowserUk (Patriarch) on Jul 30, 2015 at 16:13 UTC

      The first time you run this you will get an error because the file counts doesn't exist.

      Also, do you mean to have both @F and @f?

      Running this on my machine adds nothing to the file.

      $ pwd /Users/nick/monks $ ls | wc -l 39 $ perl -i'*' -anle"@f=</Users/nick/monks/*>; shift @F; push @F, scalar + @f; print join ' ', @F;" counts $ cat counts $
      The way forward always starts with a minimal test.
        The first time you run this you will get an error because the file counts doesn't exist.

        Yep. You need to prime it:echo 0 0 0 0 0 0 0 0 >counts

        do you mean to have both @F and @f?

        Yes. @F comes from -a (autosplit: see perlrun). @f is the array that gets the list of files; rename to your preference.


        Anyone got any experience of this phone's predecessor?

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice.
        I'm with torvalds on this Agile (and TDD) debunked I told'em LLVM was the way to go. But did they listen!

      Does not work as expected in my test.

      (1) It assumes that the counts file already exists, which it may not.
      (2) If the file is there but empty, it doesn't add anything to the file.
      (3) It changes all lines to the same value.

Re: Rolling variable
by james28909 (Deacon) on Jul 30, 2015 at 13:50 UTC
    use strict; use warnings; my @array = qw(file1 file2 file3 file4 file5 file6 file7 file8 file9); + #array with file names my @reversed_array = reverse @array; #reverse @array so reading from t +he last element my @files; #this array will contain 8 file names once done for(0 .. 7 ){ #8 iterations push @files, $reversed_array[$_]; } #print "$_\n" for reverse @files; print "$_\n" for @files;
      Hi James, Rata, Thanks for the inputs. However, I thin k this will work in a single run of the script (please correct me if I'm wrong). Since I would like to monitor in an hourly basis, that means I will call the perl script to run thru a cron. So I was thinking to save the counts in a file.
        you could easily adopt this into a script and have it run every hour. call it from your main script. spit any output to files if needed. go ahead modify it as needed :)))
        use strict; use warnings; my @file_array = qw(file1 file2 file3 file4 file5 file6 file7 file8 fi +le9); my @reversed_file_array = reverse @file_array; my @files; while (1) { for ( 0 .. 7 ) { push @files, $reversed_file_array[$_]; } print "$_\n" for @files; undef @file_array; undef @files; sleep 2; #or sleep 3600 for 1 hour }
        If you dont undef @files then it will keep a list of the filenames. You can comment it out to see if you need to undef it or not. To me though, if you have already did operations on the files in @files, then there is no need to save a list.
Re: Rolling variable
by Anonymous Monk on Jul 31, 2015 at 00:37 UTC
    In simple terms, you will have to capture the 8 most-recent observations in some sort of list, to which you will push the latest entries and then use (perldata array slices) to capture the most-recent ones. "How you persist those values" is entirely up to you.
Re: Rolling variable
by M4 (Novice) on Jul 31, 2015 at 06:53 UTC
    Your question is inconsistent. You want to keep a filecount (ls | wc -l) and record the count (>/some/dir/some.file). That is one count. Then you want to keep the 8 most recent counts? You only have one! Having said that, whatever you really mean, it sounds like something a simple shell script is better suited for than Perl, but not knowing the exact requirements, one cannot say definitely.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1136865]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (3)
As of 2024-03-19 04:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found