Durch das ganze Unix System bestimmte Dateiart suchen

S

sniper

Jungspund
Hallo,
ich will ein C Programm schreiben welches das ganze Unix System nach einer bestimmten Dateiart sucht. Am ende sollen alle Pfade ausgeben werden wo sich die Dateien befinden. Ein Teil hab ich schon geschrieben der funktioniert, nur nicht mit der gewünschten Funktion weil es nur ein Ordner durchsuchen kann. Ich muss aber das ganze System durchsuchen und ich komm nicht weiter… Hat jemand eine Idee wie es funktionieren könnte? :think:

Hier ist mein Programm:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>

// die Dateiart die gesucht wird
#define STR_EXTENSION ".xxx"
#define LENGTH_OF_STRING(x) (sizeof(x)-1)


int main () {

  struct stat FileInfo;
  struct dirent *CurrentFile;
  DIR *Directory;
  char chl_Path[256];

  int inl_ordnerZaehler = 0;
  int inl_xxxZaehler = 0;
  // von diesen Punkt fängt das Programm mit der Suche an
  char chl_anfangsPath[] = { "/" };

  /// Öffnet das Verzeichnis
  if ( (Directory = opendir(chl_anfangsPath)) == NULL) {
      perror("opendir()");
      return EXIT_FAILURE;
  }
  else {

    /// bis das Programm alle Dateien durchgelaufen hat
    while ( (CurrentFile = readdir(Directory)) != NULL) {
        int inl_slaenge = 0;

        if (strcmp(CurrentFile->d_name,".") && strcmp(CurrentFile->d_name,"..")) {
            // kopiert den String in chl_Path
            strcpy(chl_Path,chl_anfangsPath);
            // hängt das zweite an das erste an
            strcat(chl_Path,CurrentFile->d_name);
            // brauchen wir um die Attribute der Datei ausgelesen zu können
            if (stat(chl_Path,&FileInfo) == -1) {
                perror("stat()");
                closedir(Directory);
                return EXIT_FAILURE;
            }

            /// wenn die Datei lesbar ist
            if(access(chl_Path, R_OK) == 0){

                /// wenn es sich um ein Ordner handelt
                if (S_ISDIR(FileInfo.st_mode)) {

                    // erzeugt ein array welcher alle adressen von den verschiedenen Ordner speichert
                    long il_pos[inl_ordnerZaehler];
                    // zuweisung der Adressen
                    il_pos[inl_ordnerZaehler] = telldir(Directory);
                    // erzeugt ein array welcher alle Namen von Ordner aus dem aktuellen Verzeichnis speichert
                    char chl_Ordner[inl_ordnerZaehler][128];
                    strcpy(chl_Ordner[inl_ordnerZaehler],CurrentFile->d_name);
                    printf("%d.\t",inl_ordnerZaehler+1);
                    printf("%s \t\t",chl_Path);
                    printf("pos.: %ld\n",il_pos[inl_ordnerZaehler]);
                    inl_ordnerZaehler++;
                }

                /// wenn es sich um eine Datei handelt
                else if (S_ISREG(FileInfo.st_mode)) {
                    inl_slaenge = strlen(CurrentFile->d_name);

                    char *str_rueckgabe;
                    int im_c = '.';
                    str_rueckgabe = strchr ( CurrentFile->d_name, im_c );

                       /// wenn er die ".xxx" Datei gefunden hat
                       if                      ((strcmp(STR_EXTENSION,CurrentFile->d_name+inl_slaenge-LENGTH_OF_STRING(STR_EXTENSION))) == 0){
                           char chl_xxx[inl_xxxZaehler][256];
                           strcpy(chl_xxx[inl_xxxZaehler],chl_Path);
                           printf("XXX Path: %s \n",chl_xxx[inl_xxxZaehler]);
                           inl_xxxZaehler++;
                       }
                 } // end of else if
            } // end of if (wenn die Datei lesbar ist)
        }
    } //end while
    closedir(Directory);
  } // end of else
  return EXIT_SUCCESS;
} //end main


Und so sieht die Augabe bis jetzt (sie wurde nur zur Testzwecken gemacht) wenn das Programm keine Datei gefunden hat. Wenn er die Datei findet dann steht noch der ganzer Pfad von der Datei in der Ausgabe.

Code:
1.      /bin            pos.: 2354688
2.	/dev            pos.: 2401792
3.	/etc            pos.: 2529152
4.	/lib            pos.: 2563328
5.	/mnt            pos.: 2609920
6.	/opt            pos.: 2700672
7.	/srv            pos.: 2711168
8.	/tmp            pos.: 2713728
9.	/sys            pos.: 2730880
10.	/var            pos.: 2744576
11.	/usr            pos.: 25652864
12.	/boot           pos.: 27051904
13.	/home           pos.: 29009280
14.	/proc           pos.: 29360256
15.	/sbin           pos.: 29415552
16.	/data1          pos.: 284135552
17.	/data2          pos.: 307945600
18.	/media          pos.: 1091284480
19.	/freebsd                pos.: 1383414400
 
Du musst alle directory-entries durchlaufen und prüfen, ob ein entry ein Ordner ist. Falls dies der Fall ist, muss sie die Funktion selbst aufrufen (Stichwort: Rekursion).

Mfg, Lord Kefir
 
Danke für die Antwort..
.. aber was sind genau directory-entries? Und wieso muss ich sie überprüfen wenn ich die Ordner schon herausgesucht hab mit „S_ISDIR(FileInfo.st_mode)“?

Muss ich dann mit der Funktion „getdents()“ und den Katalogen arbeiten? Ist mein Programm für irgendwas zu gebrauchen oder komplett neu schreiben?

Ich hab nicht wirklich viel Ahnung von C und Unix Systeme. Beschäftige mich jetzt erst seit paar Wochen damit.
 
Hatte ich noch auf der Platte herumfliegen:

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

void show_files (const char *dirname) {
	DIR *dir;
	struct dirent *dir_info;
	char filename[5120];
	struct stat attr;
	
	if ((dir = opendir (dirname)) != NULL) {
		while ((dir_info = readdir (dir)) != NULL) {
			if (strcmp (dir_info->d_name, ".") != 0 && strcmp (dir_info->d_name, "..") != 0) {
				if (dirname[strlen (dirname) - 1] == '/') {
					sprintf (filename, "%s%s", dirname, dir_info->d_name);
				}
				else {
					sprintf (filename, "%s/%s", dirname, dir_info->d_name);
				}

				if (stat (filename, &attr) == 0) {
					fprintf (stdout, "%s\n", filename);
					switch (attr.st_mode & S_IFMT) {
						case S_IFDIR:
							show_files (filename);
							break;
						default:
							fprintf (stdout, "%s\n", filename);
					}
				}
				else {
					fprintf (stderr, "Could not stat file: %s\n", dir_info->d_name);
				}
			}
		}		
		closedir (dir);
	}
	else {
		fprintf (stderr, "Could not open dir: %s\n", dirname);
	}
}

int main (int argc, char *argv[]) {
	show_files ("/home");

	return EXIT_SUCCESS;
}

Einziger Nachteil bei dem Code ist es, dass es eventuell zu Bufferoverflows kommen kann (Pfad + Dateiname dürfen höchstens 5120 Zeichen lang sein). Entweder Du arbeitest mit 'nem dynamischen Array oder baust 'ne Überprüfung ein, bevor Du den Dateinamen zusammensetzt.

Mfg, Lord Kefir
 
Danke!!
Das Programm wird mit bestimmt sehr helfen. ;)
 
HI,
Kann man nicht auf die Datenbank von locate zurückgreifen? Wenn das geht sollte es schneller gehn, da die DB ja schon vorhandnen ist.
Gruß, Georg
 
Dann muss slocate aber installiert und aktuell sein.

Mfg, Lord Kefir
 
Ein Tipp noch:

Man sollte besser die Funktion lstat() statt stat() verwenden weil wenn das Programm an einen Symbolischen Link oder eine rekursive Verknüpfung stoßt dann kommt man in eine endlose Schleife.
 
Mit 'stat' gibt es auch keine Probleme, da aufgrund des 'switch (attr.st_mode & S_IFMT)' im obigen Codebeispiel nur rekursive Aufrufe stattfinden, wenn auch wirklich ein directory gefunden wird.

Mfg, Lord Kefir
 
Ich hab "switch (attr.st_mode & S_IFMT)" auch in meinen Programm und ich hatte Probleme wenn ich ab den root Verzeichnis gesucht habe. Es war nicht unbedingt eine Endlosschleife aber es war auch nicht schon wenn mit das Programm mehrere male so was ausgibt /ordner1/ordner2/ordner3/ordner1/ordner2/ordner3/ordner1/ordner2/ordner3/ordner1/ordner2/ordner3/ ordner1/ordner2/ordner3/ordner1/ordner2/ordner3/ordner1/ordner2/ordner3/ordner1/ordner2/ordner3/ ordner1/ordner2/ordner3/ordner1/ordner2/ordner3/ordner1/ordner2/ordner3/ordner1/ordner2/ordner3/ ordner1/ordner2/ordner3/ordner1/ordner2/ordner3/meineDatei.xxx
Und das Programm hat über 10 Minuten nach den Dateien gesucht.. Ich weis nicht ob es je zum Ende gekommen ist weil ich keine Geduld hatte so lange zu warten.
Dann hab ich diese eine Funktion geändert und ich hätte meine gesuchte Dateien sauber auf dem Bildschirm stehen und das schon nach 3-4 Minuten auf einen 500MHz Rechner.
 
Zuletzt bearbeitet:

Ähnliche Themen

Unix Webserver mit HTML Seite erstellen

Prozesskommunikation mit PIPES - wie funktioniert das?

Ausführbare C-Datei von Mac OS auf Embedded Linux ausführen

C HTTP request

Programmpause bis parport0 sich ändert?

Zurück
Oben