opendir() stat() liefert fehlerhaften Ordner-output

Hi Liebe Community,

ich hab ein Problem mit der opendir- oder stat()-Funktion in "C" unter Linux.

Grundsätzlich erst einmal nichts spektakuläres:
Ich möchte die Verzeichnisse ausgeben die in einem
von mir benannten Ordner lokalisiert sind.


Code:
/* read_dir.c */
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  DIR *dir
  struct dirent *dirzeiger;
  struct stat attribut;
  

  /* Verzeichnis öffnen */
     if((dir=opendir(argv[1])) == NULL) {
      if((dir=opendir("./N20_L0p55/")) == NULL) 
       fprintf(stderr,"Fehler bei opendir ...\n");
       return EXIT_FAILURE;
     }
    
    
    /* Komplettes Verzeichnis auslesen */
    while((dirzeiger=readdir(dir)) != NULL){      
       printf("\t dirzeiger: %s\n",(*dirzeiger).d_name); //liefert problemlos alle Einträge
      stat( (*dirzeiger).d_name , &attribut );
      
      /*Auslassen der . und .. Verzeichniseinträge*/
      if(strcmp(".",(*dirzeiger).d_name) == 0 ||strcmp("..",(*dirzeiger).d_name) == 0){
	continue;	
      }
      
//       if( (attribut.st_mode) & S_IFDIR){ //als alternative probiert
      if(S_ISDIR(attribut.st_mode)){
//       if( (attribut.st_mode & S_IFMT) == S_IFDIR ){ //als alternative probiert
	printf("%s\n",(*dirzeiger).d_name);
      }
    }
    
    /* Lesezeiger schließen */
    if(closedir(dir) == -1)
      printf("Fehler beim Schließen von %s\n", argv[1]);
    return EXIT_SUCCESS;
  }

Verzeichnis ist folgendermaßen (Sorry leicht unübersichtlich):
-Verz_A/0/
-Verz_A/1/
-Verz_A/2/
-Verz_A/3/
-Verz_A/4/
-Verz_A/5/
-Verz_A/6/
-Verz_A/7/
-Verz_A/8/
-Verz_A/9/

-Verz_B/0
-Verz_B/1
-Verz_B/...
-....
-...

-..

Jetzt befinde ich mich in der Ebene von Verz_A und Verz_B also ist dieses Verzeichnis mein working directory "." .
Nun geb ich bei opendif("./Verz_A/")) und erwarte: 0/ bis 9/ als Verzeichnis in der Ausgabe.
Es kommen aber nur nach "." und ".." alle Dateien und Ordner die in dem "Verz_A" Ordner sind.

D.h. es fehlen Ordner und die Unterscheidung zwischen Ordner und Datei wird nicht vorgenommen... .
WENN ICH ABER nur im working directory "." bleibe funktioniert alles.

DARAUS folgt für mich ...
ich muss einen Fehler bei dem Aufruf der stat-Funktion gemacht haben da in der print Ausgabe zuvor alles ausgegeben wird.

Hat jemand eine Idee wir ich jedes beliebige Verzeichnis auslesen kann ohne in das executable in den jeweiligen Ordner zu haben?
(möglichst mit dieser Methode)

Gruß
LM
 
Hi.

Bitte beschreibe das nächste Mal nicht die Eingabe und Ausgabe, sondern zeig es uns einfach! Das ist viel verständlicher. Ungefähr so:

Code:
$ ls -R *
Verz_A:
0/  1/  2/  3/  4/  5/  6/  7/  8/  9/

Verz_B:
0/  1/  2/  3/  4/  5/  6/  7/  8/  9/
$ mein_programm Verz_A
...
Hast du dir denn mal d_name ausgeben lassen? Das enthält keineswegs einen Pfad, sondern nur den Namen des Verzeichniseintrages. Du müßtest also den Pfad noch davorhängen bevor du stat aufrufst.
 
Hi deepthroat,

danke für die Antwort.

Ich habe jetzt den Pfad eingefügt und nun wird der ganze Inhalt des Verzeichnisses angegeben.
Allerdings unterscheidet " if(S_ISDIR(attribut.st_mode)){ " nicht nach Datei oder Ordner.

wenn ich statt der Funktion S_ISDIR() die Funktion S_ISREG() benutze dann bekomme ich keine Ausgabe
obwohl Dateien in in dem Verzeichnis existieren.


als Argument beim ausführen des executables übergebe ich "Verz_A"
neuer Code:

Code:
/* read_dir.c */
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  DIR *dir=opendir(argv[1]);
  struct dirent *dirzeiger;
  struct stat attribut;
  char puffer[200];
  
  if(getcwd(puffer,sizeof(puffer))==NULL){
    fprintf(stderr,"Fehler bei getcwd...\n");
    return EXIT_FAILURE;
  }printf("WD: %s\n",puffer);
  strcat(puffer,"/");
  strcat(puffer,argv[1]);
  printf("WD: %s\n",puffer);
    /* das komplette Verzeichnis auslesen */
    while((dirzeiger=readdir(dir)) != NULL){      

//       printf("d_name: %s\n",(*dirzeiger).d_name);
      stat( puffer , &attribut );
      
      /*Auslassen der . und .. Verzeichnisses*/
      if(strcmp(".",(*dirzeiger).d_name) == 0 ||strcmp("..",(*dirzeiger).d_name) == 0) continue;

//       if( (attribut.st_mode) & S_IFDIR){
      if(S_ISREG(attribut.st_mode)){
//       if( (attribut.st_mode & S_IFMT) == S_IFDIR ){
	printf("Verzeichnis: %s\n",(*dirzeiger).d_name);
      }
    }
       
    /* Lesezeiger wieder schließen */
    if(closedir(dir) == -1)
      printf("Fehler beim Schließen von %s\n", argv[1]);
    return EXIT_SUCCESS;
  }

Ausgabe:
Code:
Verzeichnis: file_in_Verz_A_6
Verzeichnis: 9
Verzeichnis: 5
Verzeichnis: file_in_Verz_A_1
Verzeichnis: 0
Verzeichnis: file_in_Verz_A_4
Verzeichnis: file_in_Verz_A_2
Verzeichnis: 7
Verzeichnis: 6
Verzeichnis: 3
Verzeichnis: file_in_Verz_A_5
Verzeichnis: 8
Verzeichnis: file_in_Verz_A_3
Verzeichnis: 2
Verzeichnis: 1
Verzeichnis: 4

vgl mit Ausschnitt aus "ls -R"
Code:
./Verz_A:
0  1  2  3  4  5  6  7  8  9  file_in_Verz_A_1  file_in_Verz_A_2  file_in_Verz_A_3  file_in_Verz_A_4  file_in_Verz_A_5  file_in_Verz_A_6

./Verz_A/0:
file_1  file_2  file_3  file_4  file_5

./Verz_A/1:

./Verz_A/2:

./Verz_A/3:

./Verz_A/4:

./Verz_A/5:

./Verz_A/6:


Gruß
 
Die Variable puffer ändert sich in der Schleife ja gar nicht. Du rufst also stat immer mit demselben Parameter auf.

Du mußt in jedem Schleifendurchlauf einen neuen Pfad zusammenbasteln. Du mußt nicht unbedingt einen absoluten Pfad angeben, der getcwd Aufruf ist also unnötig.
 
Super und danke deepthroat ******


Hier das funktionierende Programm :

Code:
/* read_dir.c */
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  DIR *dir=opendir(argv[1]);
  struct dirent *dirzeiger;
  struct stat attribut;
  char puffer[200];
  

  /* das komplette Verzeichnis auslesen */
  while((dirzeiger=readdir(dir)) != NULL){
    /*Auslassen der . und .. Verzeichnisses*/
    if(strcmp(".",(*dirzeiger).d_name) == 0 ||strcmp("..",(*dirzeiger).d_name) == 0) continue;

    strcat(puffer,argv[1]);
    strcat(puffer,dirzeiger->d_name);
//     printf("d_name: %s\n",(*dirzeiger).d_name);
    stat( puffer , &attribut );
    
      if(S_ISDIR(attribut.st_mode)){
	  printf("Verzeichnis: %s\n",(*dirzeiger).d_name);
	}
	puffer[0]='\0';
      }
      
      /* Lesezeiger wieder schließen */
      if(closedir(dir) == -1)
	printf("Fehler beim Schließen von %s\n", argv[1]);
      return EXIT_SUCCESS;
    }
 
Eine kleine Optimierung könnte man noch machen:
C:
char puffer[200];

strcpy(puffer, argv[1]);

size_t len = strlen(puffer);
char* end = puffer + len;

if (puffer[len-1] != '/') *(end++) = '/';

while ((dirzeiger=readdir(dir)) != NULL){
   ...

   strcpy(end, dirzeiger->d_name);

   ...
}
 

Neue Beiträge

Zurück