verzeichnisse erkennen



  • hi,
    man kann ja mit fstream mit folgenden code verzeichnisse auslesen und ausgeben lassen:

    DIR *Dir;
    struct dirent *DirEntry;
    
    Dir = opendir("verzeichnis");
    
    while(DirEntry=readdir(Dir))
    {
         cout << Dir->d_name;
    }
    

    nun möchte ich aber erkennen ob es sich bei solch einen eintrag um eine datei oder um ein verzeichniss handelt. wier stelle ich das am besten an? ich hatte mir überlegt das man jeden eintrag versuchen kann wie ein verzeichniss mit opendir() zu öffnen, wenn es geht ist es ein verzeichniss, wenn nicht eine datei. das wirkt aber leider nicht sehr proffesionell und ich denke mir das es sicher noch eine elegantere und bessere methode gibt.

    ich hab schon überall im internet und in diesen forum gesucht, aber nichts passendes was auch unter linux funktioniert gefunden.

    schonmal thx im vorraus



  • du kannst auf Verzeichnisse prüfen, indem du auf den aktuellen Dateinamen stat() anwendest und anschließend das Feld st_mode des an stat() übergebenen struct stat mit dem Makro S_ISDIR() auf ein Verzeichnis überprüfst.



  • danke erstmal, ich hab aber noch kleine probleme.
    mit deiner hilfe bin ich zu folgenden test-programm gekommen:

    #include <dirent.h>
    #include <iostream>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    
    using namespace std;
    
    int main(void)
    {
    	DIR *Dir;
    	struct dirent *DirEntry;
    	struct stat *buffer;
    	Dir = opendir("/home/dir");
    
    	while(DirEntry=readdir(Dir))
    	{
    	     cout << DirEntry->d_name;
    	     stat(DirEntry->d_name, buffer);
    
    	     if(S_ISDIR(buffer->st_mode))
    	     {
    	     	cout << " 1" << endl;
    	     }
    	     else
    	     {
    	     	cout << " 0" << endl;
    	     }
    	}
    	return 0;
    }
    

    welchens ein verzeichnis (hier das home verzeichnis) ausliest, jeden eintrag ausgibt, überprüft ob er eine datei oder ein verzeichnis ist, und dies mit einer 0 oder 1 signalisiert.

    leider ist angeblich jeder eintrag eine datei, sprich es kommt überall die 0.

    och hoffe ich hab mich jetzt verständlich genug ausgedrückt 😉



  • soweit ich weiß, befüllt dir die Funktion stat() nur einen buffer.
    Du musst dich also um das bereitstellen des Speichers kümmern. Könnte sein, dass du auf uninitialisierte Werte triffst und durch Zufall immer 0 raus kommt. Du müsstest also:

    struct stat buffer;
    //...
    stat(DirEntry->d_name, &buffer); // mit überprüfung des rückgabewertes (hab ich jetz weggelassen
    if(S_ISDIR(buffer.st_mode))
    {
    //go on read child dir
    }
    

    schreiben. Und außerdem natürlich den Rückgabewert von stat() prüfen, ich bin mir (fast) sicher, dass der bei deinem Aufruf daneben geht



  • das klappt auch nicht so recht, jetzt werden immer ca. die erste hälfte der einträge als dateien und die letztte hälfte als verzeichnisse angezeigt. sehr seltsam......



  • Was sagt denn der Rückgabewert? Müsste ja 0 sein, da Du den nach dem letzten Rat sicherlich beachtest, bevor Du auf st_mode zugreifst 😃

    Hint: In d_name steht nur der Datei-/Ordnername, wenn Du das Programm nicht gerade in /home/dir laufen lässt, wird er die beim stat nicht finden wenn Du den Pfad nicht vorne anfügst.



  • also so war er nur bei "." und ".." ungleich 0, als ich es jetzt nochmal mit dem verzeichnis in dem dem ausführbare datei ist ausrobiert habe waren alle != 0 !!!!



  • Probiers mal so:

    int main(void)
    {
        DIR *Dir;
        struct dirent *DirEntry;
        struct stat *buffer;
        string pfad = "/home/dir";
        Dir = opendir(pfad.c_str());
    
        while(DirEntry=readdir(Dir))
        {
             string pfaddatei = pfad + "/" + DirEntry->d_name;
             cout << pfaddatei;
             if (stat(pfaddatei.c_str(), buffer) == 0) {
    
             if(S_ISDIR(buffer->st_mode))
             {
                 cout << " 1" << endl;
             }
             else
             {
                 cout << " 0" << endl;
             }
    
             }
        }
        return 0;
    }
    


  • Nabend,

    schau mal, das duerfte fuer dich interessant sein:

    http://www.c-plusplus.net/forum/viewtopic.php?t=39523

    gruss
    v R



  • also bei deinem programm bekomm ich immer den bösen laufzeitfehler "Segmention fault (core dumped)". ich hab selber auch grad in der richtung getestet und mein code klappt bei mir:

    #include <dirent.h>
    #include <iostream>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    
    using namespace std;
    
    int main(void)
    {
    	DIR *Dir;
    	struct dirent *DirEntry;
    	struct stat buffer;
    	string Path = "/home/dir/";
    	string Temp;
    	Dir = opendir(Path.c_str());
    
    	while(DirEntry=readdir(Dir))
    	{
      		stat(Temp.c_str(), &buffer; //ich weiß das der rückgabewert erst noch überprüft werden muss, aber dann klappt es auf einmal nicht mehr
    
    		cout << DirEntry->d_name;
    		Temp = Path;
    		Temp += DirEntry->d_name;
    
    	   	 if(S_ISDIR(buffer.st_mode))
    	   	 {
    	   	 	cout << " 1" << endl;
    	   	 }
        	 else
    		 {
    	   		cout << " 0" << endl;
    	     }
    	}
    	return 0;
    }
    


  • du könntest auch zu dem jeweiligen Verzeichnis mit chdir() hinwechseln. Allerdings gibt das Probleme, falls du jemals daran denkst, das ganze Multi-Threaded zu machen.
    Noch was:
    Vielleicht ist die Rekursionstiefe auch zu hoch (klingt jetzt komisch, Tiefe zu hoch ^^), dann kanns sein, dass es auch nimmer klappt, jedenfalls für den Fall, dass du, im Falle eines Verzeichnisses, in dieses wechselst und dann dort weiter suchst und so, dann müsstest du das sichere readdir_r verwenden (würde ich ohnehin empfehlen).



  • Hallo,

    wo segfaulted der Code denn? Waere gut zu wissen, damit die FAQ diesbezueglich
    gefixt werden kann.

    Ein moeglicher Fehler kann sein, dass die Rekursionstiefe zu hoch ist, wie
    bereits von meinem Vorposter angemerkt. Ich weiss grad gar nicht, ob ich auf
    dieses Problem im FAQ-Code hingewiesen hab oder nicht, muss ich mal schauen.

    Ich hoffe aber, dass das Prinzip klar geworden ist.

    gruss
    v R



  • hi,
    also der segmentation fault tritt in zeile 9 auf, also wenn die schleife das erste mal betreten wird.

    ich hab auch nchmal eine frage zu dem code den ich as letztes gepostet hab, da sitzt nämlich irgendwo der wurm drin, ich hab nämlich mitbekommen das da auch manchmal dateien als verzeichnisse und verzeichnisse als dateien ausgegeben werden und ich weiß nicht warum. hat da vllt jemand eine ahnung?



  • dir schrieb:

    hi,
    also der segmentation fault tritt in zeile 9 auf, also wenn die schleife das erste mal betreten wird.

    ich hab auch nchmal eine frage zu dem code den ich as letztes gepostet hab, da sitzt nämlich irgendwo der wurm drin, ich hab nämlich mitbekommen das da auch manchmal dateien als verzeichnisse und verzeichnisse als dateien ausgegeben werden und ich weiß nicht warum. hat da vllt jemand eine ahnung?

    Ist das denn so schwer? Wenn am Anfang der Schleife ein segmentation fault auftritt, dann hast Du einen Zeiger, der nicht dahin zeigt, wo er soll. Ein Kandidat dafür wäre der Zeiger "Dir", den Du als Parameter übergibst. Den bekommst Du von opendir zurück. Dann schaust Du in die man page (oder besser Du schaust erst in die man page und fängst erst dann an zu codieren). Die sagt Dir, daß opendir im Fehlerfall NULL zurück gibt und errno entsprechend setzt.

    Also mal wieder ein einfacher Fall, wo der Entwickler einfach nur zu bequem war, von anfang an die Fehlerprüfung vollständig zu machen und deswegen jetzt stundenlang rumgrübelt statt einfach die Fehlermeldung anzuschauen. 🙄

    Leute - immer an die Fehlerprüfung denken ⚠ ⚠ ⚠.



  • jup, das war auch der fehler, danke

    aber der code macht immernoch nicht das was er machen soll

    #include <dirent.h>
    #include <iostream>
    
    #include <sys/types.h>
    #include <sys/stat.h>
    
    using namespace std;
    
    int main(void)
    {
        DIR *Dir;
        struct dirent *DirEntry;
        struct stat buffer;
        string Path = "/home/dir/";
        string Temp = Path;
        if((Dir = opendir(Path.c_str())) == 0)
    	{
    		cerr << "fehler beim oeffnen des verzeichnisses." << endl;
    		return 0;
    	}
    
        while(DirEntry=readdir(Dir))
        {
            if(stat(Temp.c_str(), &buffer) == 0)
    		{
            	Temp = Path;
            	Temp += DirEntry->d_name;
    
    			cout << Temp;
    
                if(S_ISDIR(buffer.st_mode))
                {
                    cout << " verzeichnis" << endl;
                }
             	else
             	{
             		cout << " datei" << endl;
            	}
    		}
        }
        return 0;
    }
    

    wieso sind immernoch angeblich manche dateien verzeichnisse und manche verzeichnisse dateien? es ist sicher bloß wieder so ne dumme kleine sache wo man nicht dran denkt und immer wieder drüber liest.

    ich hoffe mir kann nochmal jemand helfen



  • Beim ersten Schleifendurchlauf steht Temp auf dem Initialwert "/home/dir". Und darauf machst Du ein stat. Schau Dir den Code noch mal genau an. Oder bau Dir doch einfach mal ein "cout << Temp << endl;" vor das stat ein. Da wirst Du Dich wundern, was da raus kommt 😉



  • abgesehen davon machst du bei jedem Schleifendurchlauf den stat() Aufruf auf den vorher zusammengesetzten Pfad und nicht auf den aktuellen.


Anmelden zum Antworten