Au chapitre 4 du livre "Programmation avancée dans l'environnement Unix", qui couvre les fichiers et les répertoires, il y a un exemple de code qui ressemble à la commande ftw
une hiérarchie de fichiers. Il utilise un pointeur vers un chemin de fichier absolu, ainsi qu'une fonction récursive avec un rappel pour parcourir le répertoire, en utilisant les appels à opendir()
et readdir()
dans le processus.Traversée de répertoire avec chdir() au lieu de chemins absolus
Il existe un exercice dans lequel les lecteurs sont invités à utiliser chdir()
et les noms de fichiers au lieu d'utiliser les chemins absolus pour accomplir la même tâche et comparer les heures des deux programmes. J'ai écrit un programme en utilisant chdir()
et n'a pas remarqué de différence dans le temps. Est-ce prévu? J'aurais pensé que l'appel supplémentaire à chdir()
ajouterait un peu de frais généraux. Est-ce peut-être un appel relativement trivial? Toute idée serait appréciée.
est ici la fonction récursive en utilisant des chemins absolus:
static int /* we return whatever func() returns */
dopath(Myfunc* func)
{
struct stat statbuf;
struct dirent *dirp;
DIR *dp;
int ret;
char *ptr;
if (lstat(fullpath, &statbuf) < 0) /* stat error */
return(func(fullpath, &statbuf, FTW_NS));
if (S_ISDIR(statbuf.st_mode) == 0) /* not a directory */
return(func(fullpath, &statbuf, FTW_F));
/*
* It's a directory. First call func() for the directory,
* then process each filename in the directory.
*/
if ((ret = func(fullpath, &statbuf, FTW_D)) != 0)
return(ret);
ptr = fullpath + strlen(fullpath); /* point to end of fullpath */
*ptr++ = '/';
*ptr = 0;
if ((dp = opendir(fullpath)) == NULL) /* can't read directory */
return(func(fullpath, &statbuf, FTW_DNR));
while ((dirp = readdir(dp)) != NULL) {
if (strcmp(dirp->d_name, ".") == 0 ||
strcmp(dirp->d_name, "..") == 0)
continue; /* ignore dot and dot-dot */
strcpy(ptr, dirp->d_name); /* append name after slash */
if ((ret = dopath(func)) != 0) /* recursive */
break; /* time to leave */
}
ptr[-1] = 0; /* erase everything from slash onwards */
if (closedir(dp) < 0)
err_ret("can't close directory %s", fullpath);
return(ret);
}
Et voici la fonction avec mes changements:
static int /* we return whatever func() returns */
dopath(Myfunc* func, char* path)
{
struct stat statbuf;
struct dirent *dirp;
DIR *dp;
int ret;
if (lstat(path, &statbuf) < 0) /* stat error */
return(func(path, &statbuf, FTW_NS));
if (S_ISDIR(statbuf.st_mode) == 0) /* not a directory */
return(func(path, &statbuf, FTW_F));
/*
* It's a directory. First call func() for the directory,
* then process each filename in the directory.
*/
if ((ret = func(path, &statbuf, FTW_D)) != 0)
return(ret);
if (chdir(path) < 0)
return(func(path, &statbuf, FTW_DNR));
if ((dp = opendir(".")) == NULL) /* can't read directory */
return(func(path, &statbuf, FTW_DNR));
while ((dirp = readdir(dp)) != NULL) {
if (strcmp(dirp->d_name, ".") == 0 ||
strcmp(dirp->d_name, "..") == 0)
continue; /* ignore dot and dot-dot */
if ((ret = dopath(func, dirp->d_name)) != 0) /* recursive */
break; /* time to leave */
}
if (chdir("..") < 0)
err_ret("can't go up directory");
if (closedir(dp) < 0)
err_ret("can't close directory %s", fullpath);
return(ret);
}
Merci pour la perspicacité et les autres fonctions! – rsa