Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   
Forentreff 2012     
Bücher-Shop mit Amazon (Buchkategorien)C++ : Referenzen zu C++ : C++ Builder : Visual C++ : C# : Java : Spieleprogrammierung : Systemprogrammierung Linux : Software-Entwicklung : .NET : Compilertechnik : Algorithmen & Datenstrukturen : Objektorientierung : Entwurfsmuster : UML : eXtreme Programming : Scrum : Projektmanagement : Software-Testing : Datenbanken : Tom DeMarco : Dilbert : User Friendly
C/C++ Forum :: FAQ - Linux/Unix ::  Bewegen in Verzeichnissen unter Unix     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
virtuell Realisticer
Mitglied

Benutzerprofil
Anmeldungsdatum: 07.05.2000
Beiträge: 3460
Beitrag virtuell Realisticer Mitglied 21:11:00 05.05.2002   Titel:   Bewegen in Verzeichnissen unter Unix            Zitieren

Thema: Bewegen in Verzeichnissen unter Linux/Unix
Was benoetigt man?

Nun grundsaetzlich kann ich nicht sagen, was du benötigst,
da es immer davon abhängt, was genau man programmieren will. Aber
ich denke, dass ich die wichtigsten Dinge zusammentragen kann.

Ich werde ein paar Funktionen vorstellen und das ganze anhand eines
Beispieles (Ein Directory kopieren) mehr erklären. Sollte ich Fehler
machen, bitte ich natürlich um Korrektur!

Okay, also was benätige ich?

Zu erst einmal muss ich feststellen können, ob es sich bei einer
Dateiart um ein Directory, eine Normale Datei (regular file) oder
eine spezielle Art einer Datei (special file) handelt.
Zu diesem Zweck gibt es drei Funktionen:

int stat ( const char *PathName, struct stat *Buffer ); [stat(2)]
int fstat ( int FD, struct stat *Buffer ); [fstat(2)]
int lstat ( const char *PathName, struct stat *Buffer ); [lstat(2)]

Diese Funktionen sind in der Headerdatei <sys/stat.h>
definiert. Ebenfalls wird die Headerdatei <sys/types.h>
benoetigt.

Wer ein Unixsystem nutzt, sollte darauf Acht geben, wie
die Headerdateien includiert werden, da bei manchen Unixsystemen
keine Rekursive Includierung der Headerdateien untereinander vor-
handen ist. Im o. Fall saehe eine Includierung so aus:

C/C++ Code:
#include <sys/types.h>
#include
<sys/stat.h>
C/C++ Code:
#include <sys/types.h>
#include
<sys/stat.h>
C/C++ Code:
#include <sys/types.h>
#include
<sys/stat.h>


Kurze Erlaeuterung der Funktionen:

int stat ( const char *PathName, struct stat *Buffer );

Schreibt die Attribute der Datei, die in 'PathName' spezifiziert ist,
in die Strukturvariable 'Buffer'. Handelt es sich bei der unter
'PathName' spezifizierten Datei um einen symbolischen Link, so werden
die Attribute der Datei, auf die der symbolische Link zeigt, in die
Strukturvariable 'Buffer' geschrieben.
(siehe stat(2))

int fstat ( int FD, struct stat *Buffer );

Schreibt die Attribute der schon geoeffneten Datei mit dem Datei-
descriptor 'FD' in die Strukturvariable 'Buffer'
(siehe fstat(2))

int lstat ( const char *PathName, struct stat *Buffer );

Verhaelt sich wie die stat-Funktion, mit dem Unterschied, dass, wenn
es sich bei der unter 'PathName' spezifizierten Datei um einen
symbolischen Link, so werden die Attribute dieses symbolischen Links
selbst in die Strukturvariable 'Buffer' geschrieben.
(siehe lstat(2))

Aufbau der Struktur 'stat'

Die Struktur kann sich in den einzelnen Unix-Distributionen etwas
unterscheiden, sie sollte allerdings so aussehen:

Alle drei Funktionen geben zurueck: 0 bei Erfolg; -1 bei Fehler

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct stat
{
    mode_t  st_mode;      //Dateiart und Zugriffsrechte
    ino_t   st_ino;       //i-node Nummer
    dev_t   st_dev;       //Geraetenummer (Dateisystem)
    dev_t   st_rdev;      //Geraetenummer fuer Geraetedatei
    nlink_t st_nlink;     //Anzahl der Links auf die Datei
    uid_t   st_uid;       //User-ID des Eigentuemers
    gid_t   st_gid;       //Group-ID des Eigentuemers
    off_t   st_size;      //Groeße in Byte fuer normale Dateien
    time_t  st_atime;     //Zeit d. letzten Zugriffs (access time)
    time_t  st_mtime;     /*Zeit d. letzten Aenderung in der Datei
                            (modification time)*/

    time_t  st_ctime;     //Zeit der letzten Aenderung der i-node
    long    st_blksize;   //voreingestellte Blockgroeße
    long    st_blocks;    //Anzahl der benoetigten 512-Byte-Bloecke
};
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct stat
{
mode_t st_mode; //Dateiart und Zugriffsrechte
ino_t st_ino; //i-node Nummer
dev_t st_dev; //Geraetenummer (Dateisystem)
dev_t st_rdev; //Geraetenummer fuer Geraetedatei
nlink_t st_nlink; //Anzahl der Links auf die Datei
uid_t st_uid; //User-ID des Eigentuemers
gid_t st_gid; //Group-ID des Eigentuemers
off_t st_size; //Groeße in Byte fuer normale Dateien
time_t st_atime; //Zeit d. letzten Zugriffs (access time)
time_t st_mtime; /*Zeit d. letzten Aenderung in der Datei
(modification time)*/

time_t st_ctime; //Zeit der letzten Aenderung der i-node
long st_blksize; //voreingestellte Blockgroeße
long st_blocks; //Anzahl der benoetigten 512-Byte-Bloecke
};
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct stat
{
    mode_t  st_mode;      //Dateiart und Zugriffsrechte
    ino_t   st_ino;       //i-node Nummer
    dev_t   st_dev;       //Geraetenummer (Dateisystem)
    dev_t   st_rdev;      //Geraetenummer fuer Geraetedatei
    nlink_t st_nlink;     //Anzahl der Links auf die Datei
    uid_t   st_uid;       //User-ID des Eigentuemers
    gid_t   st_gid;       //Group-ID des Eigentuemers
    off_t   st_size;      //Groeße in Byte fuer normale Dateien
    time_t  st_atime;     //Zeit d. letzten Zugriffs (access time)
    time_t  st_mtime;     /*Zeit d. letzten Aenderung in der Datei
                            (modification time)*/

    time_t  st_ctime;     //Zeit der letzten Aenderung der i-node
    long    st_blksize;   //voreingestellte Blockgroeße
    long    st_blocks;    //Anzahl der benoetigten 512-Byte-Bloecke
};


Alle Elemente, bis auf st_rdev, st_blksize und
st_blocks, sind von POSIX.1 vorgeschrieben und sind auf allen
Systemen vorhanden.

Ihr koennt die Funktionsweise von der stat-Funktion ja einmal aus-
probieren, indem ihr ein kleines Programm schreibt. Das koennte dann
ungefaehr so aussehen:

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include
<stdlib.h>
#include
<sys/types.h>
#include
<sys/stat.h>

int main() {
    char PathName[30];
    struct stat FileInfo;
    printf("Pfad + Dateiname:  ");
    scanf("%s",PathName);
    if (stat(PathName,&FileInfo) == -1) {
      perror("stat()");
      return EXIT_FAILURE;
    }
    if (S_ISREG(FileInfo.st_mode))
      puts("Normale Datei");
    else
      puts("Spezielle Datei");
    return EXIT_SUCCESS;
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include
<stdlib.h>
#include
<sys/types.h>
#include
<sys/stat.h>

int main() {
char PathName[30];
struct stat FileInfo;
printf("Pfad + Dateiname: ");
scanf("%s",PathName);
if (stat(PathName,&FileInfo) == -1) {
perror("stat()");
return EXIT_FAILURE;
}
if (S_ISREG(FileInfo.st_mode))
puts("Normale Datei");
else
puts("Spezielle Datei");
return EXIT_SUCCESS;
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include
<stdlib.h>
#include
<sys/types.h>
#include
<sys/stat.h>

int main() {
    char PathName[30];
    struct stat FileInfo;
    printf("Pfad + Dateiname:  ");
    scanf("%s",PathName);
    if (stat(PathName,&FileInfo) == -1) {
      perror("stat()");
      return EXIT_FAILURE;
    }
    if (S_ISREG(FileInfo.st_mode))
      puts("Normale Datei");
    else
      puts("Spezielle Datei");
    return EXIT_SUCCESS;
}


In diesem Code taucht ein Makro auf: S_ISREG()

Es gibt eine Reihe von Makros, die Auskunft darueber geben, um was
es sich bei einer Datei handelt. Ich werde hier alle vom POSIX.1
vorgeschriebenen Makros kurz beschreiben. Die Makros werden immer
auf das Element st_mode einer Stat-Strukturvariablen
angewandt.

S_ISREG()
Liefert einen Wert ungleich 0, wenn es sich um eine regulaere Datei
handelt

S_ISDIR()
Liefert einen Wert ungleich 0, wenn es sich um ein Directory handelt

S_ISCHR()
Liefert einen Wert ungleich 0, wenn es sich um ein zeichenorientiertes
Geraet handelt

S_ISBLK()
Liefert einen Wert ungleich 0, wenn es sich um ein blockorientiertes
Geraet handelt

S_ISFIFO()
Liefert einen Wert ungleich 0, wenn es sich um eine Pipe oder FIFO
handelt

Ihr koennt ja mit diesen Makros ein wenig experimentieren.

Kommen wir nun zu den Funktionen, die wir benoetigen um uns unter
Linux/Unix in Diretorys fortzubewegen.

DIR *opendir ( const char *Path ); [opendir(3)]
-> Rueckgabe: DIR-Zeiger bei Erfolg; NULL bei Fehler
struct dirent *readdir ( DIR *Ptr ); [readdir(3)]
-> Rueckgabe: dirent-Zeiger bei Erfolg; NULL bei Fehler
void rewinddir ( DIR *Ptr ); [rewinddir(3)]
int closedir ( DIR *Ptr ); [closedir(3)]
-> Rueckgabe: 0 bei Erfolg; -1 bei Fehler

Wie man sieht, benoetigt man noch mehr. Naemlich die Struktur
DIR und dirent.

Die Struktur DIR ist eine Systeminterne Struktur, die Infor-
mationen ueber das zu lesende Directory speichert.

dirent ist eine Struktur, die laut POSIX.1 mindestens den
Dateinamen enthalten muss. Sie kann auch noch die i-node-Nummer
enthalten.

Diese Struktur ist wie folgt definiert:

C/C++ Code:
struct dirent
{
    char   d_name[NAME_MAX + 1];  //Dateiname mit '\0'
    ino_t  d_ino;                 //i-node-Nummer
};
C/C++ Code:
struct dirent
{
char d_name[NAME_MAX + 1]; //Dateiname mit '\0'
ino_t d_ino; //i-node-Nummer
};
C/C++ Code:
struct dirent
{
    char   d_name[NAME_MAX + 1];  //Dateiname mit '\0'
    ino_t  d_ino;                 //i-node-Nummer
};


Die Strukturen und die o. g. Funktionen sind in der Headerdatei
<dirent.h> definiert.

Kurze Erlaeuterung der Funktionen:

DIR *opendir ( const char *Path );
Oeffnen des Directory 'Path'
(siehe opendir(3))

struct dirent *readdir ( DIR *Ptr );
Mit 'readdir' ließt man schrittweiße die Eintraete in einem Directory
Der erste Aufruf liefert die erste Datei in einem Directory, jeder
weitere Aufruf die naechste Datei. Dabei muessten die Dateien nicht
in der Reihenfolge gelesen werden, wie es ein 'ls -l'-Befehl anzeigt
(siehe readdir(3))

void rewinddir ( DIR *Ptr );
Setzt den Lesezeiger zurueck auf den Anfang der Namesliste des
Directorys
(siehe rewinddir(3))

int closedir ( DIR *Ptr );
Schließt ein Directory wieder (wer haetts gedacht ;) )
(siehe closedir(3))

Das ist eigentlich schon alles. Ich werde die Rechte eines Directorys
jetzt mal nicht beachten. Dafuer muesste ich fuer die Rechte etwas
mehr ausholen. Das kann ich ja dann machen, wenn mir wiedermal
langweilig ist :D .

Machen wir mal ein kleines Beispiel. Einfach ein Programm, welches
den Inhalt eines Directorys ausließt und ausgibt, ob es sich um
eine regulaere Datei handelt oder nicht.

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include
<stdlib.h>
#include
<errno.h>
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<dirent.h>

int main () {
    struct stat FileInfo;
    struct dirent *CurrentFile;
    DIR *Directory;
    char Path[30];
    if ( (Directory = opendir("/tmp")) == NULL) {
      perror("opendir()");
      return EXIT_FAILURE;
    }
    while ( (CurrentFile = readdir(Directory)) != NULL) {
      if (strcmp(CurrentFile->d_name,".") &&
             strcmp(CurrentFile->d_name,".."))
      {
        strcpy(Path,"/tmp/");
        strcat(Path,CurrentFile->d_name);
        printf ("%s \t:",Path);
        if (stat(Path,&FileInfo) == -1) {
          perror("stat()");
          closedir(Directory);
          return EXIT_FAILURE;
        }
        if (S_ISREG(FileInfo.st_mode))
          puts("Regulaere Datei");
        else if (S_ISDIR(FileInfo.st_mode))
          puts("Directory");
        else
          puts("Spezielle Datei");
      }
    } //end while
    closedir(Directory);
    return EXIT_SUCCESS;
} //end main
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include
<stdlib.h>
#include
<errno.h>
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<dirent.h>

int main () {
struct stat FileInfo;
struct dirent *CurrentFile;
DIR *Directory;
char Path[30];
if ( (Directory = opendir("/tmp")) == NULL) {
perror("opendir()");
return EXIT_FAILURE;
}
while ( (CurrentFile = readdir(Directory)) != NULL) {
if (strcmp(CurrentFile->d_name,".") &&
strcmp(CurrentFile->d_name,".."))
{
strcpy(Path,"/tmp/");
strcat(Path,CurrentFile->d_name);
printf ("%s \t:",Path);
if (stat(Path,&FileInfo) == -1) {
perror("stat()");
closedir(Directory);
return EXIT_FAILURE;
}
if (S_ISREG(FileInfo.st_mode))
puts("Regulaere Datei");
else if (S_ISDIR(FileInfo.st_mode))
puts("Directory");
else
puts("Spezielle Datei");
}
} //end while
closedir(Directory);
return EXIT_SUCCESS;
} //end main
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include
<stdlib.h>
#include
<errno.h>
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<dirent.h>

int main () {
    struct stat FileInfo;
    struct dirent *CurrentFile;
    DIR *Directory;
    char Path[30];
    if ( (Directory = opendir("/tmp")) == NULL) {
      perror("opendir()");
      return EXIT_FAILURE;
    }
    while ( (CurrentFile = readdir(Directory)) != NULL) {
      if (strcmp(CurrentFile->d_name,".") &&
             strcmp(CurrentFile->d_name,".."))
      {
        strcpy(Path,"/tmp/");
        strcat(Path,CurrentFile->d_name);
        printf ("%s \t:",Path);
        if (stat(Path,&FileInfo) == -1) {
          perror("stat()");
          closedir(Directory);
          return EXIT_FAILURE;
        }
        if (S_ISREG(FileInfo.st_mode))
          puts("Regulaere Datei");
        else if (S_ISDIR(FileInfo.st_mode))
          puts("Directory");
        else
          puts("Spezielle Datei");
      }
    } //end while
    closedir(Directory);
    return EXIT_SUCCESS;
} //end main


Erklärung zum Code:
Zunaechst einmal legen wir ein paar Variablen an. Die ersten drei
dürften jetzt klar sein. Die vierte ist dafür da, den aktuellen
Pfadname + Dateiname zu speichern, damit wir die stat-Funktion
ordnungsgemäß aufrufen können.

Als nächstes öffnen wir das Directory '/tmp'.
Danach lesen wir solange aus dem Directory, bis wir an das Ende
angelangen. Die 'Directorys' "." und ".." (Current Directory und
Parent Directory) muessen abgefangen werden. Wuerde man immer "."
lesen, waere es Fatal und man haette eine Endlosschleife. Das selbe
mit "..".
Danach kopieren wir in die Variable 'Path' den Pfad + Dateinamen, so
dass wir so ein Format bekommen: '/PathName/FileName'.
Nun holen wir uns die Informationen ueber diese Datei, werten diese
aus und geben die entsprechende Message aus. Sind wir am Ende des
Directorys angelangt, schließen wir das Directory und das Programm
ist beendet.

War ja gar nicht so schwer *g*.

Okay. Dann koennen wir ja jetzt unser Programm schreiben, mit dem
wir ein Directory rekursiv kopieren koennen. Das Programm wird
sicherlich nicht PERFEKT sein. Ich werde auch keine Prüfung von
Rechten hineinbringen oder sowas. Aber das hab ich ja bereits gesagt.

Was wir benötigen, ist eine Funktion, die ein Directory durchläuft
und eine Funktion, die Dateien ins neue Directory kopiert.
symbolische Links werde ich abfangen und nicht mitkopieren.

Nennen wir die Funktionen Copy und ReadSrcDir (ja, ja, es gibt
bestimmt bessere Namen, aber mir fallen grad keine ein :p ).

Die main-Funktion werd ich mir sparen, die kann dann jeder grad
selbst schreiben und die Funktionen mit den noetigen Parametern
aufrufen.

Fangen wir mit der Copy-Funktion an. Was muss sie können? Sie muss
eine Datei von einem Directory in das andere kopieren.

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void Copy(const char *Src,const char *Dst) {
     size_t ReadBytes;
     const int Max = 255;
     char Buffer[Max];
     FILE *FileIn;
     FILE *FileOut;
     if ( (FileIn = fopen(Src,"r")) == NULL)
       return;
     if ( (FileOut = fopen(Dst,"w") ) == NULL) {
       fclose(FileIn);
       return;
     }
 
     printf("Kopiere %s nach %s...\n",Src,Dst);

     //Solange aus Datei gelesen wird
     while ( (ReadBytes = fread(Buffer,1,Max,FileIn)) > 0)
       //wird auch in Datei geschrieben
       if (fwrite(Buffer,1,ReadBytes,FileOut) != ReadBytes) {
         fclose(FileIn);
         fclose(FileOut);
         return;
       }

     puts("Fertig!");

     fclose(FileIn);
     fclose(FileOut);
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void Copy(const char *Src,const char *Dst) {
size_t ReadBytes;
const int Max = 255;
char Buffer[Max];
FILE *FileIn;
FILE *FileOut;
if ( (FileIn = fopen(Src,"r")) == NULL)
return;
if ( (FileOut = fopen(Dst,"w") ) == NULL) {
fclose(FileIn);
return;
}

printf("Kopiere %s nach %s...\n",Src,Dst);

//Solange aus Datei gelesen wird
while ( (ReadBytes = fread(Buffer,1,Max,FileIn)) > 0)
//wird auch in Datei geschrieben
if (fwrite(Buffer,1,ReadBytes,FileOut) != ReadBytes) {
fclose(FileIn);
fclose(FileOut);
return;
}

puts("Fertig!");

fclose(FileIn);
fclose(FileOut);
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void Copy(const char *Src,const char *Dst) {
     size_t ReadBytes;
     const int Max = 255;
     char Buffer[Max];
     FILE *FileIn;
     FILE *FileOut;
     if ( (FileIn = fopen(Src,"r")) == NULL)
       return;
     if ( (FileOut = fopen(Dst,"w") ) == NULL) {
       fclose(FileIn);
       return;
     }
 
     printf("Kopiere %s nach %s...\n",Src,Dst);

     //Solange aus Datei gelesen wird
     while ( (ReadBytes = fread(Buffer,1,Max,FileIn)) > 0)
       //wird auch in Datei geschrieben
       if (fwrite(Buffer,1,ReadBytes,FileOut) != ReadBytes) {
         fclose(FileIn);
         fclose(FileOut);
         return;
       }

     puts("Fertig!");

     fclose(FileIn);
     fclose(FileOut);
}


Soweit so gut. Diese Funktion sollte die Quelldatei ins Zieldirectory
kopieren.

Kommen wir nun zur eigentlichen Funktion. Die Funktion, die das
Directory durchlaeuft.

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
void ReadSrcDir(const char *Src,const char *Dst) {
     /*Wir benötigen natürlich Strukturvariablen von DIR, dirent
       und stat*/

     DIR *Directory;
     struct dirent *CurrentFile;
     static struct stat FileInfo;
     /*Wir benötigen eine Variable, mit der wir einen Absoluten
      Pfadnamen + Datei speichern*/

     char PathName[255]; //Wer weiß wie tief das Directory geht?
     char PathName2[255]; //Hier solls hin gehn -:)
     //Directory öffnen

     if ( (Directory = opendir(Src)) == NULL)
       return;
     if (stat(Src,&FileInfo) == -1) {
       closedir ( Directory );
       return;
     }
     /*Nun legen wir das Zieldirectory an, falls es schon
       existiert, geben wir eine entsprechende Meldung aus*/

     if (mkdir(Dst,FileInfo.st_mode) == -1) {
       /*Wir fangen nur diesen Fehler ab. Falls es einen anderen
         Fehler gibt, beenden wir das Programm. Das kann natuerlich
         so haendeln wie er will*/

       if ( errno == EEXIST )
         puts("Directory existiert bereits");
       else {
         closedir(Directory);
         return;
                   
       }
     }
     else
       printf ( "Directory %s anlegen\n", Dst );
     //Nun fangen wir an, das Directory zu lesen
     while ( (CurrentFile = readdir(Directory)) != NULL) {
       /*Prüfen, ob es sich um das Current Directory
         (".") oder um das Parent Directory ("..")
         handelt. Wenn ja, dann passiert nichts.*/

       if (strcmp(CurrentFile->d_name,".") &&
           strcmp(CurrentFile->d_name,".."))
       {
         /*Nun bauen wir uns den Pfad zusammen, damit
           wir mit der stat-Funktion die Attribute
           erfragen können*/

         strcpy(PathName,Src);
         strcat(PathName,"/");
         strcat(PathName,CurrentFile->d_name);
         if (stat(PathName,&FileInfo) == -1) {
           closedir ( Directory );
           return;
         }
         /*Handelt es sich um ein Verzeichnis?*/
         if (S_ISDIR(FileInfo.st_mode)) {
           strcpy(PathName2,Dst);
           strcat(PathName2,"/");
           strcat(PathName2,CurrentFile->d_name);
           ReadSrcDir(PathName,PathName2);
         }
         /*oder handelt es sich um eine regulaere Datei?*/
         else if ( S_ISREG ( FileInfo.st_mode ) ) {
           strcpy(PathName2,Dst);
           strcat(PathName2,"/");
           strcat(PathName2,CurrentFile->d_name);
           Copy(PathName,PathName2);
         }
       }
    } //end while
} //end ReadSrcDir
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
void ReadSrcDir(const char *Src,const char *Dst) {
/*Wir benötigen natürlich Strukturvariablen von DIR, dirent
und stat*/

DIR *Directory;
struct dirent *CurrentFile;
static struct stat FileInfo;
/*Wir benötigen eine Variable, mit der wir einen Absoluten
Pfadnamen + Datei speichern*/

char PathName[255]; //Wer weiß wie tief das Directory geht?
char PathName2[255]; //Hier solls hin gehn -:)
//Directory öffnen

if ( (Directory = opendir(Src)) == NULL)
return;
if (stat(Src,&FileInfo) == -1) {
closedir ( Directory );
return;
}
/*Nun legen wir das Zieldirectory an, falls es schon
existiert, geben wir eine entsprechende Meldung aus*/

if (mkdir(Dst,FileInfo.st_mode) == -1) {
/*Wir fangen nur diesen Fehler ab. Falls es einen anderen
Fehler gibt, beenden wir das Programm. Das kann natuerlich
so haendeln wie er will*/

if ( errno == EEXIST )
puts("Directory existiert bereits");
else {
closedir(Directory);
return;

}
}
else
printf ( "Directory %s anlegen\n", Dst );
//Nun fangen wir an, das Directory zu lesen
while ( (CurrentFile = readdir(Directory)) != NULL) {
/*Prüfen, ob es sich um das Current Directory
(".") oder um das Parent Directory ("..")
handelt. Wenn ja, dann passiert nichts.*/

if (strcmp(CurrentFile->d_name,".") &&
strcmp(CurrentFile->d_name,".."))
{
/*Nun bauen wir uns den Pfad zusammen, damit
wir mit der stat-Funktion die Attribute
erfragen können*/

strcpy(PathName,Src);
strcat(PathName,"/");
strcat(PathName,CurrentFile->d_name);
if (stat(PathName,&FileInfo) == -1) {
closedir ( Directory );
return;
}
/*Handelt es sich um ein Verzeichnis?*/
if (S_ISDIR(FileInfo.st_mode)) {
strcpy(PathName2,Dst);
strcat(PathName2,"/");
strcat(PathName2,CurrentFile->d_name);
ReadSrcDir(PathName,PathName2);
}
/*oder handelt es sich um eine regulaere Datei?*/
else if ( S_ISREG ( FileInfo.st_mode ) ) {
strcpy(PathName2,Dst);
strcat(PathName2,"/");
strcat(PathName2,CurrentFile->d_name);
Copy(PathName,PathName2);
}
}
} //end while
} //end ReadSrcDir
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
void ReadSrcDir(const char *Src,const char *Dst) {
     /*Wir benötigen natürlich Strukturvariablen von DIR, dirent
       und stat*/

     DIR *Directory;
     struct dirent *CurrentFile;
     static struct stat FileInfo;
     /*Wir benötigen eine Variable, mit der wir einen Absoluten
      Pfadnamen + Datei speichern*/

     char PathName[255]; //Wer weiß wie tief das Directory geht?
     char PathName2[255]; //Hier solls hin gehn -:)
     //Directory öffnen

     if ( (Directory = opendir(Src)) == NULL)
       return;
     if (stat(Src,&FileInfo) == -1) {
       closedir ( Directory );
       return;
     }
     /*Nun legen wir das Zieldirectory an, falls es schon
       existiert, geben wir eine entsprechende Meldung aus*/

     if (mkdir(Dst,FileInfo.st_mode) == -1) {
       /*Wir fangen nur diesen Fehler ab. Falls es einen anderen
         Fehler gibt, beenden wir das Programm. Das kann natuerlich
         so haendeln wie er will*/

       if ( errno == EEXIST )
         puts("Directory existiert bereits");
       else {
         closedir(Directory);
         return;
                   
       }
     }
     else
       printf ( "Directory %s anlegen\n", Dst );
     //Nun fangen wir an, das Directory zu lesen
     while ( (CurrentFile = readdir(Directory)) != NULL) {
       /*Prüfen, ob es sich um das Current Directory
         (".") oder um das Parent Directory ("..")
         handelt. Wenn ja, dann passiert nichts.*/

       if (strcmp(CurrentFile->d_name,".") &&
           strcmp(CurrentFile->d_name,".."))
       {
         /*Nun bauen wir uns den Pfad zusammen, damit
           wir mit der stat-Funktion die Attribute
           erfragen können*/

         strcpy(PathName,Src);
         strcat(PathName,"/");
         strcat(PathName,CurrentFile->d_name);
         if (stat(PathName,&FileInfo) == -1) {
           closedir ( Directory );
           return;
         }
         /*Handelt es sich um ein Verzeichnis?*/
         if (S_ISDIR(FileInfo.st_mode)) {
           strcpy(PathName2,Dst);
           strcat(PathName2,"/");
           strcat(PathName2,CurrentFile->d_name);
           ReadSrcDir(PathName,PathName2);
         }
         /*oder handelt es sich um eine regulaere Datei?*/
         else if ( S_ISREG ( FileInfo.st_mode ) ) {
           strcpy(PathName2,Dst);
           strcat(PathName2,"/");
           strcat(PathName2,CurrentFile->d_name);
           Copy(PathName,PathName2);
         }
       }
    } //end while
} //end ReadSrcDir


So, das wars auch schon. Hoffe ich hab keine Fehler eingebaut, sonst
korrigiert mich einfach. Ist leider nicht sehr einfach, den Über-
blick zu behalten, da das Textfeld hier nicht so breit ist. Egal,
ich hoffe das Prinzip ist klar geworden.

mfg
v R

C++
Wer unter C++ Objekt Orientiert programmieren will und sich nicht mit der POSIX C API abmühen möchte, sollte sich folgende Librarys angucken

  • Boost::Filesystem - ein Teil der Boost Library (Portabel für viele Systeme)
  • More - more::io enthält Klassen und Funktionen zum Umgang mit Dateien (nur für POSIX Systeme)

_________________
virtuell Realisticer, innen gut, aussen besser


Zuletzt bearbeitet von rüdiger am 16:32:49 10.08.2004, insgesamt 4-mal bearbeitet
Werbeunterbrechung
C/C++ Forum :: FAQ - Linux/Unix ::  Bewegen in Verzeichnissen unter Unix   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können keine Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum nicht antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.