Re: Limiting a glob
by moritz (Cardinal) on Mar 09, 2009 at 17:39 UTC
|
| [reply] |
|
| [reply] [d/l] |
Re: Limiting a glob
by swampyankee (Parson) on Mar 09, 2009 at 17:51 UTC
|
Don't use glob; use opendir and readdir to loop through the directory entries. Strip out file types you don't want to move (directories, system files, hidden files, etc) and use rename or File::Copy's move function. Alternatively, you can push the files you want to move in an array, move the files when the array is either filled or you run out of files (I think it's quite unlikely that the number of files mod 100 will be 0); in the former case, empty the array and iterate; in the latter, you're done.
Now, are you moving 100 files into a new directory for each 100 files or moving all the files into a single new directory?
Information about American English usage here and here. Floating point issues? Please read this before posting. — emc
| [reply] |
|
| [reply] |
|
| [reply] |
|
Re: Limiting a glob
by jethro (Monsignor) on Mar 09, 2009 at 17:43 UTC
|
perl -e 'while ($s=<*>) { print $s,"\n"; sleep 5 }'
As you can see a glob can read filenames one file at a time (hopefully perl really buffers the filenames in the background and doesn't read them in all at once). You might change it to something like this:
use strict;
use warnings;
my @files;
my $filecount=0;
while (my $s=<*>) {
push @files, $s;
if (++$filecount>=100) {
DoTheMoveWith(@files);
$filecount=0;
}
}
DoTheMoveWith(@files) if (@files);
| [reply] [d/l] [select] |
|
#!/usr/bin/perl
use strict;
use warnings;
mkdir "gtest" or die "screaming";
for (1..40000) {
open my $f,">","gtest/$_" or die "gnashing";
close $f or die "howling";
}
my $c=0;
while (my $r=glob("gtest/*")) {
$c++;
if ($c == 1) {
for (1..40000) {
unlink "gtest/$_" or die "wailing"
}
}
}
print "$c\n";
rmdir "gtest" or die "exhausted";
I believe this is done so that glob returns a consisten snapshot of the directory contents as they were at some point, regardless of whether the content changes while you process the results. If you want more up-to-date data, with only current files being returned, you'll have to use opendir and readdir.
| [reply] [d/l] |
|
perl reads the entire list of files returned by glob into memory at once.
This is what I originally assumed, hence my original question. So, I guess that makes the answer to my question, "No, you can't set a limit on a glob."
Thanks
| [reply] |
|
Thanks. This illustrates a basic misunderstanding I had of the way glob actually works internally.
| [reply] |
Re: Limiting a glob
by zentara (Archbishop) on Mar 09, 2009 at 18:58 UTC
|
Of course, the obligatory.....
while(1){print "help, the globs are coming\n"}
Someone showed me this once here, I didn't actually check it out, but it looked impressive ...famous last words See: bad bad glob
| [reply] [d/l] |
Re: Limiting a glob
by dwm042 (Priest) on Mar 09, 2009 at 20:57 UTC
|
Given the small number of files you're reading into an array at once (40,000 names isn't a lot, really), I'd grab all of them and then use an array slice to operate on subsets of your array until finished.
Check also here, and here.
| [reply] |
Re: Limiting a glob
by hbm (Hermit) on Mar 10, 2009 at 16:56 UTC
|
A word from the field, and sorry it took me awhile to track down my notes:
I have a script that worked fine for months, doing something like my @pdfs = glob("$path/*.pdf");. One day the script failed, and with use diagnostics; I got this:
internal error: glob failed at ...
(P) Something went wrong with the external program(s) used for glob and <*.c>. This may mean that your csh (C shell) is broken. If so, you should change all of the csh-related variables in config.sh: If you have tcsh, make the variables refer to it as if it were csh (e.g. full_csh='/usr/bin/tcsh'); otherwise, make them all empty (except that d_csh should be 'undef') so that Perl will think csh is missing. In either case, after editing config.sh, run ./Configure -S and rebuild Perl.
There were not "too many files", which I had seen before with glob. This was new... The environment is out of my hands, so I simply gave up with glob and used File::Find.
| [reply] [d/l] [select] |