2008-12-19 5 views
5

Ich verwende das Modul File::Find, um einen Verzeichnisbaum zu durchlaufen. Sobald ich eine bestimmte Datei gefunden habe, möchte ich die Suche beenden. Wie kann ich das machen?Wie kann ich aus der rekursiven Suchfunktion ausbrechen, sobald eine bestimmte Datei gefunden wurde?

find (\$processFile, $mydir); 

    sub processFile() { 
     if ($_ =~ /target/) { 
     # How can I return from find here? 
     } 
    } 
+0

Meinst du das "File :: Find" -Modul anstelle von "File :: Found"? – BrianH

+0

Ja, danke. Ich habe die Frage bearbeitet. – MCS

Antwort

9

Scheint, wie Sie sterben müssen wird:

eval { 
    find (\$processFile, $mydir); 
}; 

if ([email protected]) { 
    if ([email protected] =~ m/^found it/) { 
     # be happy 
    } 
    else ([email protected]) { 
     die [email protected]; 
    } 
} 
else { 
    # be sad 
} 


sub processFile() { 
    if ($_ =~ /target/) { 
     die 'found it'; 
    } 
} 
+0

Das scheint zu funktionieren. Ich bin ziemlich neu in Perl - ist das ein typischer Einsatz von Eval? – MCS

+1

Sehr. Siehe "perldoc -f eval". –

+0

Es ist im Grunde eine Ausnahme ohne eine Klasse. Wenn Sie mehr Kontrolle haben und sicherstellen möchten, dass es nicht nur einen anderen Fehler gibt, der "gefunden" entspricht, können Sie etwas wie Exception :: Class verwenden. – mpeters

1

Können Sie benutzerdefinierte Ausnahmen in Perl auslösen?

+0

Ich denke, es gibt ein Modul dafür, aber es ist ein Hack. – Keltia

+0

Übergeben Sie einfach ein Objekt an die Stelle von() statt einer Zeichenkette. –

-4

Die Funktion process() sollte true zurück, wenn er die Datei findet, und andernfalls false. Jedes Mal, wenn sich diese Prozessdatei selbst aufruft, sollte dieser Rückgabewert überprüft werden. Wenn es wahr ist, hat ein rekursiver Aufruf die Datei gefunden, so dass es nicht nötig ist, sich selbst erneut anzurufen, und es muss auch wahr zurückgegeben werden. Wenn es falsch ist, wurde die Datei noch nicht gefunden und sollte die Suche fortsetzen.

+0

So funktioniert File :: Find nicht. –

+0

Es ist möglicherweise nicht korrekt für File :: Find, aber es ist ein korrekter Weg für eine handgerollte rekursive Suchfunktion (alle rekursiven Funktionen müssen eine Möglichkeit haben, zu beenden, und dies ist ein akzeptabler Weg, dies zu tun). –

-1

fand ich diesen Link:

http://www.perlmonks.org/index.pl?node_id=171367

ich eines der Skripte in dieser Liste der Beiträge kopiert, und dies scheint zu funktionieren:

#! /usr/bin/perl -w 

use strict; 
use File::Find; 

my @hits =(); 
my $hit_lim = shift || 20; 

find(
    sub { 
     if(scalar @hits >= $hit_lim) { 
      $File::Find::prune = 1; 
      return; 
     } 
     elsif(-d $_) { 
      return; 
     } 
     push @hits, $File::Find::name; 
    }, 
    shift || '.' 
); 

$, = "\n"; 
print @hits, "\n"; 

es, dass scheint verursacht Fund tatsächlich mit $ File :: Find :: prune nicht mehr durchqueren.

+0

Ich habe versucht, $ File :: Find :: Prune zu setzen und es hat nicht funktioniert.Es scheint so, als würde die Einstellung von Prune auf ein Verzeichnis die Suche nach dem Abstieg in dieses Verzeichnis stoppen, aber es wird nicht daran gehindert, weitere Verzeichnisse (oder Dateien) zu bearbeiten. – MCS

+0

Okay - Wenn ich dieses Skript oben starte, schneidet es bei 20 Ergebnissen ab und von dem, was ich sagen kann, stoppt es auch die Suchfunktion. (Das Hinzufügen des "return" könnte nur verhindern, dass Ergebnisse zum Array hinzugefügt werden, aber ich bin mir ziemlich sicher, dass File :: Find tatsächlich stoppt). Tut mir leid, es funktioniert nicht für dich ... – BrianH

0

Sie könnten benannte Blöcke verwenden und zu ihr springen, wenn Sie Ihr Ergebnis finden (mit dem nächsten, letzten hängt es davon ab, was Sie brauchen).

3

Zusätzlich zu dem, was alle anderen sagten, können Sie sich auch File-Find-Object ansehen, das sowohl iterativ (und damit in der Mitte unterbrochen) als auch instanziierbar ist (sodass Sie mehrere initiieren und verwenden können) sofort, oder instanziieren ein FFO-Objekt basiert während der Durchführung einer anderen Überprüfung, etc.)

Der Nachteil ist, dass es nicht Kern ist, aber es hat nur Class :: Accessor als eine Abhängigkeit, und ist pure-Perl Es sollte also nicht schwer sein, sie zu installieren.

Ich sollte Sie warnen, dass ich sein Betreuer bin, also kann ich ein bisschen voreingenommen sein.