2010-02-07 17 views
7

Ich verwende Glib in meiner Anwendung, und ich sehe, es gibt Convenience-Wrapper in Glib für C remove, unlink und rmdir. Diese funktionieren jedoch nur für eine einzelne Datei oder ein Verzeichnis gleichzeitig.Wie gehe ich ein Verzeichnis in C

Soweit ich sehen kann, enthalten weder der C-Standard noch Glib irgendeine Art von rekursiven Directory-Walk-Funktionalität. Ich sehe auch keine spezifische Möglichkeit, einen gesamten Verzeichnisbaum auf einmal zu löschen, wie mit rm -rf.

Für das, was ich tue, mache ich mir keine Sorgen über irgendwelche Komplikationen wie Berechtigungen, Symlinks sichern den Baum (unendliche Rekursion), oder alles, was eine sehr naive Implementierung ausschließen würde ... also bin ich nicht abgeneigt, meine eigene Funktion dafür zu schreiben.

Allerdings bin ich neugierig, ob diese Funktionalität irgendwo in den Standardbibliotheken gtk oder glib (oder in einer anderen leicht wiederzuverwendenen C-Bibliothek) bereits vorhanden ist und ich einfach nicht darüber gestolpert bin. Wenn Sie dieses Thema googlen, werden viele falsche Leads generiert.

Ansonsten mein Plan ist, diese Art von Algorithmus zu verwenden:

dir_walk(char* path, void* callback(char*) { 
    if(is_dir(path) && has_entries(path)) { 
    entries = get_entries(path); 
    for(entry in intries) { dir_walk(entry, callback); } 
    } 
    else { callback(path) } 
} 

dir_walk("/home/user/trash", remove); 

Offensichtlich ich in einem gewissen Fehlerbehandlung bauen würde und dergleichen um den Vorgang abzubrechen, sobald ein schwerwiegender Fehler aufgetreten ist.

+1

technisch nur 'remove()' ist in der C-Norm, die anderen 2 sind POSIX :) –

+0

Gut zu wissen, danke. – mlibby

+1

Zusätzlich zu den vorhandenen Antworten, bitte beachten Sie, dass man nicht einfach * ein Verzeichnis * nach Mordor laufen lässt, sei es in C oder einer anderen Sprache. –

Antwort

4

Sie können GFileEnumerator verwenden, wenn Sie es mit glib tun möchten.

+1

erinnert mich an 'os.walk()' –

+0

Ist ein GFileEnumerator rekursiv? Ich habe die Dokumentation gelesen, erwähne sie aber nicht. Natürlich kann ich es ausprobieren und herausfinden ... – mlibby

+2

Nein, ist es nicht. Es gibt einige Tutorials, aber Sie sollten einen Blick auf http://gezeiten.org/post/2009/04/Writing-Your-Own-GIO-Jobs werfen, der eine rekursive Dateiauflistung zeigt (suchen Sie nach "g_file_deep_count"). – AndiDog

2

Standard-C-Bibliotheken sollen primitive Funktionalität bieten. Worüber du sprichst, ist das zusammengesetzte Verhalten. Sie können es einfach mit den Low-Level-Funktionen implementieren, die in Ihrer bevorzugten API vorhanden sind - take a look at this tutorial.

7

Haben Sie sich <dirent.h> angesehen? AFAIK gehört zu der POSIX-Spezifikation, die Teil der Standardbibliothek der meisten, wenn nicht aller C-Compiler sein sollte. Siehe z.B. this <dirent.h> reference (Single UNIX specification Version 2 by the Open Group).

P.S., bevor jemand dazu Stellung nimmt: Nein, dies bietet kein rekursives Verzeichnis-Traversal. Aber ich denke, das wird am besten vom Entwickler umgesetzt; Die Anforderungen können sehr unterschiedlich sein, so dass die rekursive Traversierungsfunktion in einer Größe für alle sehr leistungsfähig sein muss. (Z. B. Sind symlinks nachverfolgt? Sollte die rekursivtiefe begrenzt sein? Etc.)

+0

An Fenstern ist es geöffnet/geschlossen und dergleichen. Oder FindFirstFile FindNextFile. –

5

Mehrere Plattformen gehören ftw und nftw: "(neue) Datei Baum gehen". Das Überprüfen der Manpage auf einem Imac zeigt, dass es sich um Legacy handelt und neue Benutzer fts bevorzugen sollten. Portabilität kann ein Problem mit einer dieser Möglichkeiten sein.

-1

Beachten Sie, dass die "Convenience-Wrapper" Sie entfernen erwähnen(), unlink() und rmdir(), vorausgesetzt, Sie sind die, die in <glib/gstdio.h> erklärt bedeuten, sind nicht wirklich "Convenience-Wrapper". Was ist praktisch, wenn man Standardfunktionen mit einem "g_" voranstellt? (Und beachte, dass ich das sage, auch wenn ich sie an erster Stelle vorstelle.)

Der einzige Grund, warum diese Wrapper existieren, ist für Dateinamensprobleme unter Windows, wo diese Wrapper tatsächlich aus echtem Code bestehen; Sie verwenden Dateinamen in Unicode, die in UTF-8 codiert sind. Die entsprechenden "unverpackten" Microsoft C-Bibliotheksfunktionen nehmen Dateinamen in Systemcodepage.

Wenn Sie nicht speziell Code schreiben, der für Windows portierbar ist, gibt es keinen Grund, die Wrapper von g_remove() usw. zu verwenden.

+2

Der Vorteil ist, dass die g_ Versionen die besprochenen Fälle behandeln. Da ich glib und gtk für viele andere Dinge verwende, macht es Sinn, konsistent zu sein und die g_ Funktionen zu verwenden. Wenn Sie dies nicht tun, ist sichergestellt, dass mein Code nicht übertragbar ist. Ich wollte damit nicht implizieren, dass die g_-Versionen nur die Standardbibliothek aufgerufen haben. – mlibby

Verwandte Themen