http://www.perlmonks.org?node_id=584666

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

Hi monks!

I'm attempting find all "pl" files in machine,and store to database.below is my code:
#!/usr/bin/perl #use Getopt::Long; use strict; use File::Find; use DBI qw(:sql_types); my @search_result; # find files find (\&wanted,"."); #save to database. foreach (@search_result) { my @file_stat = stat; save_data(@file_stat,$_); } sub wanted { if(/\.pl$/i) { push @search_result,$File::Find::name; } } sub save_data { my $sql = q(insert into file_stat values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)) +; my $dbh = DBI->connect('dbi:ODBC:test','test','test123',{AutoCommi +t => 1,RaiseError => 1}) or die "error!!\n"; my $sth = $dbh->prepare($sql); my $count = 1; foreach (@_) { if($count==14) { $sth->bind_param(14,$_); } else { $sth->bind_param($count,$_,SQL_INTEGER); } $count ++; } $sth->execute; }
questions:
1. @search_results will be much large if files is too many.I want to deal with files "streamly",other than push all to array. any suggestion?

2. $count is ugly,have any built-in variable?

Thanks in advance!!!!

Replies are listed 'Best First'.
Re: regarding File::Find
by chromatic (Archbishop) on Nov 17, 2006 at 07:00 UTC

    Answer #1: you can do your insert within wanted().

    Answer #2: pass a list of values to execute() instead of using bind_param() and counting.

      Thanks for your reply!

      I think my mention has some problems.

      for 1, I mean "insert" and "find" are running in parallel.
      for 2, if use execute,how declare sql_type?
        I think the solution chromatic had in mind goes something like this (untested)
        #!/usr/bin/perl use strict; use File::Find; use DBI; my $sql = q(insert into file_stat values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)) +; my $dbh = DBI->connect('dbi:ODBC:test','test','test123',{AutoCommit => + 1,RaiseError => 1}) or die "error!!\n"; my $sth = $dbh->prepare($sql); sub wanted { return unless /\.pl$/i; my @stats = stat $File::Find::name; $sth->execute(@stats, $File::Find::name); } # find files find (\&wanted,".");

        Update: fixed stupid mistake in code (return instead of next).

        -- Hofmator

        Code written by Hofmator and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: regarding File::Find
by quester (Vicar) on Nov 17, 2006 at 07:13 UTC
    1. You might try the simple approach:
    sub wanted { if (/\.pl$/i) { $_ = $File::Find::name; save_data(stat ($_), $_); } }

    2. Well, not exactly. You could separate the special last case out of the loop. You could also iterate $_ over the integers 1 to 13 and index into @_ for the values, which would look like this:

    $sth -> bind_param ($_, @_[$_], SQL_INTEGER) foreach (1..13); $sth -> bind_param (14, @_[14]);
Re: regarding File::Find
by inman (Curate) on Nov 17, 2006 at 12:59 UTC
    The following code uses the list as a buffer. The wanted method adds the value to the buffer and only saves the buffer if it has a reached a certain length.
    #! /usr/bin/perl -w use strict; use Data::Dumper; use File::Find; my @search_result; find (\&wanted,"."); save_data(); sub wanted { return unless /\.pl$/i; push @search_result,$File::Find::name; if (@search_result == 10) { # save buffer and empty if 10 results save_data(@search_result); @search_result = (); } } # stubbed! sub save_data { print join(',',@search_result),"\n"; }