godirwalk ist eine Bibliothek zum Durchqueren eines Verzeichnisbaums auf einem Dateisystem.
Kurz gesagt, warum habe ich diese Bibliothek erstellt?
filepath.Walk .filepath.Walk .filepath.Walk .filepath.Walk .Abhängig von Ihren spezifischen Umständen benötigen Sie möglicherweise keine Bibliothek mehr für das Gehen von Dateien in Go.
Zusätzliche Beispiele finden Sie in den examples/ dem Unterverzeichnis.
Diese Bibliothek normalisiert den bereitgestellten Verzeichnisnamen auf der Basis des osspezifischen Pfadabscheiders, indem Sie filepath.Clean für sein erstes Argument aufrufen. Es liefert jedoch immer den Pathname, der erstellt hat, indem der richtige osspezifische Pfadabscheider verwendet wird, wenn die angegebene Rückruffunktion aufgerufen wird.
dirname := "some/directory/root"
err := godirwalk . Walk ( dirname , & godirwalk. Options {
Callback : func ( osPathname string , de * godirwalk. Dirent ) error {
// Following string operation is not most performant way
// of doing this, but common enough to warrant a simple
// example here:
if strings . Contains ( osPathname , ".git" ) {
return godirwalk . SkipThis
}
fmt . Printf ( "%s %s n " , de . ModeType (), osPathname )
return nil
},
Unsorted : true , // (optional) set true for faster yet non-deterministic enumeration (see godoc)
}) Diese Bibliothek bietet nicht nur Funktionen für das Durchqueren eines Dateisystemverzeichnisbaums, sondern auch für die Erzielung einer Liste von unmittelbaren Nachkommen eines bestimmten Verzeichnisses, in der Regel viel schneller als die Verwendung von os.ReadDir oder os.ReadDirnames .
Hier ist der Grund, warum ich godirwalk für filepath.Walk , os.ReadDir und os.ReadDirnames benutze.
filepath.Walk Im Vergleich zu filepath.Walk in Benchmarks wurde beobachtet, dass es zwischen dem fünf- und zehnfachen der Geschwindigkeit für Darwin läuft, bei der Geschwindigkeit, die mit dem der Unix find -Nützlichkeit vergleichbar ist. und ungefähr die doppelte Geschwindigkeit auf Linux; und ungefähr das Vierfache der Geschwindigkeit an Fenstern.
Wie erhält es diesen Leistungsschub? Es leistet weniger Arbeit, um Ihnen fast die gleiche Ausgabe zu geben. Diese Bibliothek ruft dieselben syscall auf, um die Arbeit zu erledigen, aber sie tätigt weniger Anrufe, wirft keine Informationen ab, die sie möglicherweise benötigt, und schafft weniger Speicherverkehr auf dem Weg, indem derselbe Scratch -Puffer für das Lesen aus einem Verzeichnis wiederum verwendet wird, anstatt einen neuen Puffer neu zu vermitteln, wenn sie Dateisystemeingabedaten aus dem Betriebssystem lesen.
Während des Durchquerens eines Dateisystemverzeichnisbaums erhält filepath.Walk die Liste der sofortigen Nachkommen eines Verzeichnisses und wirft die Knoten -Typinformationen für den Dateisystemeintrag weg, der vom Betriebssystem bereitgestellt wird, der mit dem Namen des Knotens geliefert wird. Unmittelbar vor dem Aufrufen der Rückruffunktion ruft filepath.Walk os.Stat für jeden Knoten auf und übergibt die zurückgegebenen os.FileInfo -Informationen an den Rückruf.
Während die von os.Stat bereitgestellten os.FileInfo Informationen äußerst hilfreich sind-und sogar die os.FileMode -Daten enthalten-müssen für jeden Knoten zusätzliche Systemaufrufe erforderlich sind.
Da sich die meisten Rückrufe nur darum kümmern, was der Knotentyp ist, werfen diese Bibliothek die Typinformationen nicht weg, sondern liefert diese Informationen in Form eines os.FileMode -Werts der Rückruffunktion. Beachten Sie, dass der bereitgestellte os.FileMode -Wert, den diese Bibliothek nur bereitstellt, über die Knoten -Typinformationen verfügt und nicht über die Berechtigungsbits, klebrigen Bits oder andere Informationen aus dem Modus der Datei enthält. Wenn sich der Rückruf um die gesamte os.FileInfo -Datenstruktur eines bestimmten Knotens kümmert, kann der Rückruf bei Bedarf os.Stat aufrufen und nur bei Bedarf.
$ go test -bench=. -benchmem
goos: darwin
goarch: amd64
pkg: github.com/karrick/godirwalk
BenchmarkReadDirnamesStandardLibrary-12 50000 26250 ns/op 10360 B/op 16 allocs/op
BenchmarkReadDirnamesThisLibrary-12 50000 24372 ns/op 5064 B/op 20 allocs/op
BenchmarkFilepathWalk-12 1 1099524875 ns/op 228415912 B/op 416952 allocs/op
BenchmarkGodirwalk-12 2 526754589 ns/op 103110464 B/op 451442 allocs/op
BenchmarkGodirwalkUnsorted-12 3 509219296 ns/op 100751400 B/op 378800 allocs/op
BenchmarkFlameGraphFilepathWalk-12 1 7478618820 ns/op 2284138176 B/op 4169453 allocs/op
BenchmarkFlameGraphGodirwalk-12 1 4977264058 ns/op 1031105328 B/op 4514423 allocs/op
PASS
ok github.com/karrick/godirwalk 21.219s$ go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: github.com/karrick/godirwalk
BenchmarkReadDirnamesStandardLibrary-12 100000 15458 ns/op 10360 B/op 16 allocs/op
BenchmarkReadDirnamesThisLibrary-12 100000 14646 ns/op 5064 B/op 20 allocs/op
BenchmarkFilepathWalk-12 2 631034745 ns/op 228210216 B/op 416939 allocs/op
BenchmarkGodirwalk-12 3 358714883 ns/op 102988664 B/op 451437 allocs/op
BenchmarkGodirwalkUnsorted-12 3 355363915 ns/op 100629234 B/op 378796 allocs/op
BenchmarkFlameGraphFilepathWalk-12 1 6086913991 ns/op 2282104720 B/op 4169417 allocs/op
BenchmarkFlameGraphGodirwalk-12 1 3456398824 ns/op 1029886400 B/op 4514373 allocs/op
PASS
ok github.com/karrick/godirwalk 19.179sfilepath.WalkIch habe mich bisher auch nicht darum gekümmert, aber Humor mich. Wir alle lieben, wie wir einmal schreiben und überall rennen können. Es ist wichtig für die Einführung, das Wachstum und den Erfolg der Sprache, dass die von uns erstellte Software für alle Architekturen und Betriebssysteme, die von GO unterstützt werden, nicht modifiziert werden kann.
Wenn das Traversed -Dateisystem eine logische Schleife hat, die durch symbolische Links zu Verzeichnissen verursacht wird, ignoriert walk symbolische Links und durchquert den gesamten filepath.Walk ohne Fehler. Unter Windows wird jedoch filepath.Walk weiterhin symbolische Verzeichnisse verfolgen, obwohl dies nicht zu bewirken ist, und letztendlich dazu führen, dass filepath.Walk früh endet und einen Fehler zurückgibt, wenn der Pfadname zu lang wird, von endlosen Schleifen symbolischer Links auf den Pfadname zu verkürzen. Dieser Fehler kommt von Windows, übergeht durch filepath.Walk und an den vorgelagerten Client, filepath.Walk ausgeführt wird.
Das Mitnehmen ist, dass das Verhalten unterschiedlich ist, basierend auf der Plattform filepath.Walk läuft. Dies ist zwar eindeutig nicht beabsichtigt, bis es in der Standardbibliothek festgelegt ist, aber ein Kompatibilitätsproblem darstellt.
Diese Bibliothek behebt das obige Problem so, dass sie niemals logische Datei -SYTEM -Schleifen auf Unix oder Windows folgt. Darüber hinaus folgt es nur den symbolischen Links, wenn FollowSymbolicLinks nach. Das Verhalten unter Windows und anderen Betriebssystemen ist identisch.
filepath.Walk Während diese Bibliothek das Verhalten der unglaublich gut geschriebenen filepath.Walk Bibliothek nachahmt, gibt es Orte, an denen sie ein wenig abweicht, um eine einfachere oder intuitivere Anrufer-Schnittstelle zu bieten.
Da diese Bibliothek nicht auf os.Stat auf jedem Dateisystem -Knoten aufgerufen wird, ist es für die Rückruffunktion kein möglicher Fehlerereignis für die Filterung. Das dritte Argument im filepath.WalkFunc -Funktionssignatur, um den Fehler vom os.Stat zu übergeben. Statt an die Rückruffunktion nicht mehr erforderlich, und somit von der Signatur der Rückruffunktion aus dieser Bibliothek beseitigt.
Darüber hinaus beseitigt dieser geringfügige Schnittstellenunterschied zwischen filepath.WalkFunc und der WalkFunc dieser Bibliothek den Boilerplate -Code, den Callback -Handler schreiben müssen, wenn sie filepath.Walk verwenden. Anstelle jeder Rückruffunktion, die den in ihn übergebenen Fehlerwert überprüfen muss, und entsprechend den Abzweigung haben, haben Benutzer dieser Bibliothek nicht einmal einen Fehlerwert, um sofort nach dem Eintritt in die Rückruffunktion zu überprüfen. Dies ist eine Verbesserung sowohl bei der Laufzeitleistung als auch in der Codeklarheit.
In jeder OS -Plattform filepath.Walk ruft die Rückruffunktion mit einem festgelegten Pathname mit Solidus ( / ) auf. Im Gegensatz dazu ruft diese Bibliothek auf den Rückruf mit dem osspezifischen Pfadname-Separator auf und vermeidet einen Aufruf an filepath.Clean in der Rückruffunktion für jeden Knoten, bevor der angegebene Pfadname tatsächlich verwendet wird.
Mit anderen Worten, selbst unter Windows wird filepath.Walk den Rückruf mit some/path/to/foo.txt aufrufen, wobei gut geschriebene Clients vor der Arbeit mit der angegebenen Datei die Normalisierung der Pathname für jede Datei durchführen müssen. Dies ist eine versteckte Boilerplate -Anforderung, um wirklich Betriebssysteme Agnostische Rückruffunktionen zu erstellen. In Wahrheit haben viele Kunden auf UNIX entwickelt und nicht unter Windows getestet, die diese Subtilität vernachlässigen, und führen zu Softwarefehler, wenn jemand versucht, diese Software unter Windows auszuführen.
Diese Bibliothek ruft die Rückruffunktion mit somepathtofoo.txt für dieselbe Datei auf, die unter Windows ausgeführt werden, wodurch die Notwendigkeit der Normalisierung des Pfadnamens durch den Client und die Wahrscheinlichkeit, dass ein Client an UNIX arbeitet, jedoch nicht unter Windows zu verringern.
Diese Verbesserung beseitigt die Notwendigkeit für einen weiteren Code von Boilerplate in Callback -Funktionen und verbessert die Laufzeitleistung dieser Bibliothek.
godirwalk.SkipThis ist intuitiver als filepath.SkipDir Ein wohl verwirrender Aspekt der filepath.WalkFunc -Schnittstelle, die diese Bibliothek emulieren muss, ist, wie ein Anrufer die Walk -Funktion mitteilt, um Dateisystemeinträge zu überspringen. Bei sowohl filepath.Walk als auch Walk dieser Bibliothek, wenn eine Rückruffunktion ein Verzeichnis überspringen und nicht in seine Kinder abfährt, gibt sie filepath.SkipDir zurück. Wenn die Rückruffunktion filepath.SkipDir für ein Nicht-Verzeichnis zurückgibt, filepath.Walk und diese Bibliothek beendet die Verarbeitung weiterer Einträge im aktuellen Verzeichnis. Dies ist nicht unbedingt das, was die meisten Entwickler wollen oder erwarten. Wenn Sie einfach einen bestimmten Nicht-Verzeichniseintrag überspringen möchten, aber die Verarbeitungseinträge im Verzeichnis fortsetzen möchten, muss die Rückruffunktion NIL zurückgeben.
Die Auswirkungen dieses Schnittstellendesigns sind, wenn Sie eine Dateisystemhierarchie laufen und einen Eintrag überspringen möchten. Sie müssen einen anderen Wert zurückgeben, basierend auf welcher Art von Dateisystemeintrag, die der Knoten ist. Um einen Eintrag zu überspringen, müssen Sie filepath.SkipDir zurückgeben, wenn es sich um ein Verzeichnis handelt, und wenn die Eingabe kein Verzeichnis ist, müssen Sie nil zurückgeben. Dies ist eine unglückliche Hürde, mit der ich viele Entwickler beobachtet habe, mit denen sie zu kämpfen haben, einfach weil es sich nicht um eine intuitive Schnittstelle handelt.
Hier ist eine Beispiel -Rückruffunktion, die an filepath.WalkFunc -Schnittstelle haftet, damit sie einen beliebigen Dateisystemeintrag überspringen, dessen vollständige Pfadname einen bestimmten Substring enthält, optSkip . Beachten Sie, dass diese Bibliothek immer noch ein identisches Verhalten von filepath.Walk unterstützt, wenn die Rückruffunktion filepath.SkipDir zurückgibt.
func callback1 ( osPathname string , de * godirwalk. Dirent ) error {
if optSkip != "" && strings . Contains ( osPathname , optSkip ) {
if b , err := de . IsDirOrSymlinkToDir (); b == true && err == nil {
return filepath . SkipDir
}
return nil
}
// Process file like normal...
return nil
} Diese Bibliothek versucht, einige dieser in Rückruffunktionen erforderlichen Logik -Kesselplatten zu beseitigen, indem ein neuer Token -Fehlerwert SkipThis wird, der eine Rückruffunktion zurückkehrt, um den aktuellen Dateisystemeintrag zu überspringen, unabhängig davon, welche Art von Eingabe sie ist. Wenn der aktuelle Eintrag ein Verzeichnis ist, werden seine Kinder nicht aufgezählt, genau so, als hätte der Rückruf filepath.SkipDir zurückgegeben. Wenn der aktuelle Eintrag ein Nicht-Verzeichnis ist, wird der nächste Dateisystemeintrag im aktuellen Verzeichnis aufgezählt, genau so, als ob der Rückruf nil zurückgegeben hat. Die folgende Beispiel -Rückruffunktion hat ein identisches Verhalten wie die vorherige, aber weniger Kesselplatten und zugegebenermaßen Logik, die ich einfacher finde.
func callback2 ( osPathname string , de * godirwalk. Dirent ) error {
if optSkip != "" && strings . Contains ( osPathname , optSkip ) {
return godirwalk . SkipThis
}
// Process file like normal...
return nil
}filepath.Walk Das Standardverhalten dieser Bibliothek besteht darin, symbolische Links zu Verzeichnissen beim Spazierengehen eines Verzeichnisbaums zu ignorieren, genau wie filepath.Walk . Es wird jedoch die Rückruffunktion mit jedem Knoten aufgerufen, den es findet, einschließlich symbolischer Links. Wenn ein bestimmter Anwendungsfall vorhanden ist, um symbolische Links beim Durchqueren eines Verzeichnisbaums zu folgen, kann diese Bibliothek auf die Weise aufgerufen werden, indem die FollowSymbolicLinks -Konfigurationsparameter auf true festgelegt wird.
Das Standardverhalten dieser Bibliothek besteht darin, die unmittelbaren Nachkommen eines Verzeichnisses immer vor dem Besuch eines jeden Knotens zu sortieren, genau wie filepath.Walk . Dies ist normalerweise das gewünschte Verhalten. Dies ist jedoch geringfügige Leistung und Speicherstrafen, die erforderlich sind, um die Namen zu sortieren, wenn ein Verzeichnisknoten viele Einträge hat. Wenn Caller im Konfigurationsparameter Unsorted Aufzählung angibt, wird das Lesen von Verzeichnissen trägen, wenn der Anrufer Einträge konsumiert. Wenn ein bestimmter Anwendungsfall vorhanden ist, der vor dem Besuch ihrer Knoten die unmittelbaren Nachkommen des Verzeichnisses nicht sortiert hat, überspringt diese Bibliothek den Sortierschritt, wenn der Unsorted Parameter auf true gesetzt ist.
Hier ist eine interessante Lektüre der potenziellen Makzards, eine Dateisystemhierarchie in einer nicht deterministischen Reihenfolge zu durchqueren. Wenn Sie wissen, dass das Problem, das Sie lösen, nicht von den Auftragsdateien betroffen ist, ermutige ich Sie, Unsorted zu verwenden. Andernfalls überspringen Sie diese Option.
Forscher finden einen Fehler in der Python -Skript möglicherweise Hunderte von Studien betroffen
Diese Bibliothek bietet einen vorgelagerten Code mit der Möglichkeit, eine Rückruffunktion anzugeben, die für jedes Verzeichnis nach der Verarbeitung seiner Kinder aufgerufen werden soll. Dies wurde verwendet, um leere Verzeichnisse rekursiv zu löschen, nachdem das Dateisystem effizienter durchquert wurde. Ein Beispiel für diese Verwendung finden Sie im Verzeichnis für examples/clean-empties .
Diese Bibliothek bietet einen vorgelagerten Code mit der Möglichkeit, einen Rückruf anzugeben, der auf Fehler aufgerufen werden soll, die das Betriebssystem zurückgibt, sodass der Upstream -Code die nächste Vorgehensweise ermitteln kann, ob das Gehen der Hierarchie zum Stillstand der Hierarchie eingestellt werden soll, da dies kein Fehler mit dem Erhalt des Nodens, der den Fehler verursacht hatte, nicht mehr als Fehler zurückrückte, oder überspringen. Ein Beispiel für diese Verwendung finden Sie in den examples/walk-fast -Verzeichnissen.