readdir,opendir



  • Hallo erstmal,
    ich grüße alle Herzlich.
    Ich habe folgende Programmieraufgabe bekommen:

    Auch gibt es Funktionen wie readdir, opendir,die die Arbeit mit Verzeichnissen ermöglichen.
    Bezeichne FS(f) die Größe einer Datei (eines Files) f.
    Schreiben Sie ein C-Programm namens "statistics", welches von einem als 
    Kommandozeilenparameter anzugebenden Verzeichnis aus absteigend durch alle 
    Unter-Verzeichnisse ermittelt, wie viele reguläre Dateien bestimmter Größen es
    jeweils gibt. 
    Listen Sie die Angaben für die folgenden Gruppen von Dateigrößen auf:
    

    Ich weiss wie man einen Kommandozeilenparameter ließt und diesen als verzeichnis öffnet(hier im Forum gefunden).
    Das Problem, dass in einem verzeichnis Unterverzeichnisse und dateien seien können, erstens muss ich sie unterscheiden können und dann die größen von dateien ausrechnen.
    Mir ist noch nicht ganz klar wie ich das machen soll.
    Kann ihr mir ein bisschen behilflich sein?
    Wie könnte ich vorgehen?



  • bunower schrieb:

    Auch gibt es Funktionen wie readdir, opendir,die die Arbeit mit Verzeichnissen ermöglichen.
    ...
    

    Nicht dass ich wüsste. Versuchs mal hier:
    http://www.c-plusplus.net/forum/f5



  • mngbd schrieb:

    Versuchs mal hier:
    http://www.c-plusplus.net/forum/f5

    Soll ich dort nochmal ein neues Thema öffnen?



  • Die genannten Funktionen readdir,opendir,... zu finden in dirent.h gehören zum POSIX-90 Standard und sind somit nicht ganz passend zu diesem C89/C99 Forum.
    Wenn dein Compiler die o.g. Headerdatei unterstützt schreibe halt mal den Quellcode soweit du kommst und frage wieder nach.



  • Tut mir leid ich bin noch neu in C und C++, deshalb weiss ich noch nicht was POSIX-90 ist noch was C89/C99 Standard ist, sorry falls es nicht hier rein passt.

    So ich habe zumindest geschafft in C++, den inhalt eines Verzeichnisses aufzulisten.
    Hier mein Code:

    #include <iostream>
    #include <sys/types.h>
    #include <dirent.h>
    
    using namespace std;
    
    int main(int argc, char *argv[]) {
        DIR *verzeichnis;
        struct dirent *files;
        verzeichnis=opendir(argv[1]);
    
        while(files = readdir(verzeichnis))
        {
          cout<<files->d_name<<endl;
        }
        closedir(verzeichnis);
        return 0;
    }
    

    Nun ist meine Frage wie kann ich im inhalt zwischen Verzeichnissen und dateien unterscheiden bzw. die Größe der dateien ermitteln?



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (C89 und C99) in das Forum Linux/Unix verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • bunower schrieb:

    Soll ich dort nochmal ein neues Thema öffnen?

    Nachdem dich noch kein Moderator verschoben hat, wird es dir wohl niemand übel nehmen. Aber wenn du Zeit hast, hilft abwarten, dann landet der Thread wie von selbst dort.

    In deinem Code sind ausserdem noch C++-Konstrukte, die zwar nichts böses sind, aber auch nicht hierher gehören.

    Nachtrag:
    Post ins Unix-Forum gerutscht, und hier gegenstandslos.



  • bunower schrieb:

    Nun ist meine Frage wie kann ich im inhalt zwischen Verzeichnissen und dateien unterscheiden bzw. die Größe der dateien ermitteln?

    Geht iirc mit man: fstat.



  • Ich habe hier ein Beispiel für die Benutzung von fstat gefunden:
    Wie genau bekomme ich damit denn aber raus ob es sich eine Datei oder Verzeichnis handelt.

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    struct stat buffer;
    int         status;
    fildes = open("/home/cnd/mod1", O_RDWR);
    status = fstat(fildes, &buffer);
    

    Ich möchte ja nicht die Größe und die anderen Informationen auf dem Display anzeigen, sondern ich möchte die Größe in einer int Variable zwischen speichern.
    Ich habe hier folgende Informationen über den struct stat bekomen:

    struct stat {
        dev_t     st_dev;     /* ID of device containing file */
        ino_t     st_ino;     /* inode number */
        mode_t    st_mode;    /* protection */
        nlink_t   st_nlink;   /* number of hard links */
        uid_t     st_uid;     /* user ID of owner */
        gid_t     st_gid;     /* group ID of owner */
        dev_t     st_rdev;    /* device ID (if special file) */
        off_t     st_size;    /* total size, in bytes */
        blksize_t st_blksize; /* blocksize for filesystem I/O */
        blkcnt_t  st_blocks;  /* number of blocks allocated */
        time_t    st_atime;   /* time of last access */
        time_t    st_mtime;   /* time of last modification */
        time_t    st_ctime;   /* time of last status change */
    };
    

    ich sehe hier dass off_t mir nützlich sein kann, aber wie bentuze ich das?



  • if( (buffer.st_mode & S_IFMT) == S_IFDIR )
      puts("ist Verzeichnis");
    else
      puts("ist Datei");
    


  • Wutz schrieb:

    if( (buffer.st_mode & S_IFMT) == S_IFDIR )
      puts("ist Verzeichnis");
    else
      puts("ist Datei");
    

    Irgendwie stimmt das nicht ganz, denn ich bekomme auch bei Verzeichnissen die meldung dass es eine Datei ist.



  • Schau dir mal an, was die Flags im genauen bedeuten. Vielleicht ist dein vermeintliches Verzeichnis nur ein Link.



  • bunower schrieb:

    off_t     st_size;    /* total size, in bytes */
    

    ich sehe hier dass off_t mir nützlich sein kann, aber wie bentuze ich das?

    Nein, das hast Du falsch gelesen. off_t ist nur der Datentyp von st_size . Und letzteres kannst Du einfach auslesen.



  • Habt ihr vielleicht eine andere Idee wie man die aufgabe lösen könnte?
    Mein Code sieht so aus bis Jetzt:

    #include <iostream>
    #include <sys/types.h>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    using namespace std;
    
    int main(int argc, char *argv[]) {
    
        DIR *verzeichnis;
        struct dirent *files;
        struct stat buffer;
        verzeichnis=opendir(argv[1]);
    
        while(files = readdir(verzeichnis)){
    
          if((buffer.st_mode & S_IFMT) == S_IFDIR ){
    	cout<<files->d_name<<" //Verzeichnis "<<endl;     
    
          }else
    	 cout<<files->d_name<<" //Datei "<<endl;
        }
        closedir(verzeichnis);
    }
    


  • Btw, in der Manpage von man: fstat(2) ist ein recht ausführliches Beispiel, probier das mal aus und melde Dich, wenn Du da Verständnisprobleme hast.



  • nman schrieb:

    bunower schrieb:

    off_t     st_size;    /* total size, in bytes */
    

    ich sehe hier dass off_t mir nützlich sein kann, aber wie bentuze ich das?

    Nein, das hast Du falsch gelesen. off_t ist nur der Datentyp von st_size . Und letzteres kannst Du einfach auslesen.

    Gut danke stimmt, kann ich denn off_t in int umwandeln?



  • nman schrieb:

    Btw, in der Manpage von man: fstat(2) ist ein recht ausführliches Beispiel, probier das mal aus und melde Dich, wenn Du da Verständnisprobleme hast.

    Sehr schön ich beschäftige mich mal damit ein bisschen.
    Aber ich verstehe jetzt schon die ganzen Makros nicht.
    Ist zwar erklärt aber schlau werde ich dennoch nicht.
    z.B: **S_IFMT beschreibung:mask for file type SCO out-of-service inode; BSD unknown type; SVID-v2 and XPG2 have both 0 and 0100000 for ordinary file
    **
    Ich weiss dass I-node die ganze infos von einer datei enthält
    und was hat die Protection für eine aussage über eine Datei?
    wieso wird ausgerechnet damit geswitcht?



  • bunower schrieb:

    Gut danke stimmt, kann ich denn off_t in int umwandeln?

    Ja, aber da läufst Du Gefahr, falsche Ergebnisse zu bekommen.

    Sicher sind IIRC nur unsigned long und long long (C99).

    Zu Deinen Schwierigkeiten mit dem switch:

    S_IFMT     0170000   bit mask for the file type bit fields
    

    Das wird eben als Bitmaske verwendet um an die Dateityp-Bitfelder heranzukommen.

    Aber in der Manpage sind ja auch die Makros dokumentiert, es wäre ohnehin klüger, S_ISDIR und Konsorten zu benutzen.



  • Ich habe hier etwas anderes gefunden.
    Was ist denn mit dem dirent d_types?
    gibt es auch nicht aus ob es eine datei bzw. ein verzeichnis ist?
    Ich habe es mal ausgetestet, da d_types vom typ her char ist habe ich es in int umgewandelt und immer wenn es ein Verzeichnis war gibt d_types eine 4 und bei einer Datei eine 8.
    kann man denn damit arbeiten?



  • So ich habe schon ein Teil des Programms zu ende Programmiert.
    Und zwar wird von einem als Argument übergebenem verzeichnis aus alle Unter verzeichnisse rekursiv durch sucht.
    Nun habe ich ein Problem und zwar werden /.. und /. als unterverzeichnisse angenommen und deshalb wird die rekursion endlos.
    Mein Programm ist folgendes:

    #include <iostream>
    #include <sys/types.h>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <string.h>
    using namespace std;
    
    void rekstat(char* name){
      DIR *verzeichnis;
      struct dirent *files;
      verzeichnis=opendir(name);
      struct stat buffer;
        //rückgabe von d_type ist char und falls man es in int konvertiert und die rückgabe 4 ist, iste es ein verzeichnis
       //falls 8 dann eine Datei
        while(files = readdir(verzeichnis)){
    	  if((files->d_type&DT_DIR)){//verzeichnis
    	    char* tmp="/";
    	    strcat(name,tmp);
    	    strcat(name,files->d_name);
    	    //rekstat(name);
    	  }else{//datei
    	    cout<<files->d_name;  
    	    cout<<" Datei "<<endl;
    	    stat(files->d_name,&buffer);
    	    cout<<(long long )buffer.st_size<<endl;
    	  }
        }
       closedir(verzeichnis);
    }
    
    int main(int argc, char *argv[]) {
      rekstat(argv[1]);
      return 0;
    }
    

Anmelden zum Antworten