2011-01-05 9 views
0

Ich möchte, dass @list alle Dateinamen in $ root_dir enthält, die übereinstimmen * YYYYMMDD *, wo YYYYMMDD vor 25 Stunden ist.Gibt es in Perl eine knappe Möglichkeit, glob und printf zu kombinieren?

Ich versuche ...

my ($y, $m, $d) = (localtime(time - 25 * 60 * 60))[5,4,3]; 
my $pattern = sprintf('*%4d%02d%02d*',$y+1900,$m+1,$d); 
print "The pattern is $pattern\n"; 
my @files = <$pattern>; 
foreach (@files) { 
    print "$_\n"; 
} 

... sondern eine Liste von Dateien zu bekommen, erhalte ich Readline-() auf ungeöffnete Dateihandle.

Ich weiß, dass der < > Operator Variablen interpretieren kann, so < $ y $ m $ d > während zwei Drittel der Tage in den letzten drei Monaten des Jahres arbeiten würde, weil diejenigen, würden Monate und Tage, die zwei haben Ziffern, aber das ist nicht robust.

Muss ich schreiben müssen ...

$m = sprintf('%02d',$m+1); 
$d = sprintf('%02d',$d+1); 
my @files = <*$y$m$d*>; 

... oder gibt es etwas prägnanter? So etwas wie ...

# invalid code unless you want to produce the string "readline() on unopened filehandle" for some reason 
my @files = <sprintf('*%4d%02d%02d*',$y+1900,$m+1,$d)>; 
+1

meine @files = <$ {\ sprintf ('*% d% 02d% 02d *', $ y + 1900, $ m + 1, $ d)}>; – MkV

+0

oder <@ {[sprintf ('*% d% 02d% 02d *', $ y + 1900, $ m + 1, $ d)]}> – MkV

Antwort

7

Verwenden

my @files = glob($pattern); 

Der <...> Bediener viel zu bereits überlastet. Insbesondere wird <$...> als ein Dateihandle genommen.

+0

Danke für die Erläuterung, wie genau <...> überlastet ist. –

3

Ein bisschen überflüssig, statt all diesen Spielereien, könnten Sie stattdessen etwas von CPAN verwenden:

use File::Find::Rule; 

my @files = File::Find::Rule->file->name($pattern)->in($root_dir); 
+0

Es gibt keinen Grund, 'File :: Find :: Rule' zu ​​verwenden, wenn ein einfacher' glob' die Aufgabe erledigt. Ihr Code durchsucht alle Unterverzeichnisse von '$ root_dir', wenn der ursprüngliche Code dies nicht getan hat. – cjm

+0

@cjm: Das kannst du leicht mit vielleicht zehn zusätzlichen Zeichen deaktivieren und hast den zusätzlichen Vorteil, dass du dich nicht mit Glob-Nuancen befassen musst. – Hugmeir

+0

liste-kontext-glob erfüllt exakt die notwendigkeit hier; Das einzige Problem war, Globs zu verwenden, nicht Readline. Nicht sicher, dass ich das eine Nuance nennen würde. – ysth

4

<> entweder readline oder glob je nach bedeuten kann, wie es verwendet wird. Von perlop:

Wenn das, was die spitzen Klammern enthalten eine einfache skalare Variable ist (zB <$foo>), dann enthält diese Variable den Namen des Dateihandle auf eine Eingabe von oder dessen Typeglob oder einen Verweis auf die same [...]

Wenn was ist innerhalb der spitzen Klammern ist weder ein Dateihandle noch eine einfache skalare Variable einen Dateikennung Name, Typeglob oder Typeglob Referenz enthält, ist es als Muster für Dateinamen interpretiert globbed [werden. ..]

Diese Unterscheidung wird nur aus syntaktischen Gründen bestimmt. [Hervorhebung von mir]

Da $pattern ist eine einfache skalare es als Griff interpretiert und Perl versucht, eine readline zu tun. Rufen Sie glob direkt statt:

my @files = glob($pattern); 

Die Überlastung der <> ein wenig verwirrend sein kann. Es könnte helfen, wenn Sie es als eine lustige Art des Schreibens iterator->next denken. (Sowohl readline als auch glob wirken wie Iteratoren im skalaren Kontext.)

Verwandte Themen