这个例子主要完成的功能是:列出所给目录及其子目录下的所有文件的名字及其对应的路径名。
/*
* =====================================================================================
*
* Filename: BianLi.c
*
* Description: 遍历目录并输出文件名
*
* Version: 1.0
* Created: 2011年07月27日 15时33分12秒
* Revision: none
* Compiler: gcc
*
* Author: (),
* Company: NDSL UESTC
*
* =====================================================================================
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include "ourhdr.h"
void func(char *);
void find(char *);
int main(int argc, char **argv)
{
if (argc != 2){ printf("argument error.\n"); return(0);}//函数运行时需要一个参数即指定的目录
func(argv[1]);
return(0);
}
static char *fullpath; //fullpath指向全路径名的内存空间
const int pathmax=1024; //pathmax是给路径名分配空间时最大的路径名长度
void func(char *pathname)
{1、这个函数主要完成pathname的安置工作
fullpath = malloc(pathmax + 1);//给指定的路径名pathname分配内存空间
memset(fullpath, 0 ,pathmax+1);//给内存空间置0
strcpy(fullpath, pathname); //把pathname拷到刚刚分配的空间内
find(fullpath); //调用这个程序的核心函数find()
}
find的流程:
如果fullpath指向的是一个普通文件,则打印文件名及其路径名接着退出函数;
如果fullpath指向的是一个目录文件,则
1:在该路径(目录)后加上“/”,ptr指向新的路径的末尾;
2:循环该新路径名中的文件,递归调用find函数。
void find(char *fullpath)
{
struct stat statbuf; //statbuf用以存放文件的相关信息,来判断一个指定路径名是文件还是目录 DIR *dp; //调用opendir函数时返回的值,opendir返回打开指定目录名的一个目录流的指针(指针类型为DIR),这个流指向目录的第一个入口 struct dirent *dirp; //struct dirent readdir(DIR *dp),readdir返回一个dirent结构的指针,该指针是dp指向的目录流的下一个目录入口的指针 char *ptr; if( lstat(fullpath, &statbuf) < 0) //获得fullpath指向的文件信息,存放在statbuf { printf("stat error.\n"); return; }
if ( S_ISDIR(statbuf.st_mode) == 0){ //判断该fullpath指向的文件是目录文件还是普通文件,如果是普通文件则执行if语句中的语句 printf("the filename is %s\n", fullpath); return; }
if ( (dp = opendir(fullpath)) == NULL)//opendir打开fullpath { printf("opendir error.\n"); return; }//opendir出错了
ptr = fullpath + strlen(fullpath); //执行本语句前,fullpath指向的位置因情况而异,执行本句后,fullpath指向fullpath的最后一个位置 *ptr++ = '/'; //该语句相当于:*ptr='/';ptr++; *ptr = 0; //给ptr一个结尾,这三句的意思是:既然这个fullpath指向的是一个路径名,则把此路径名加上一个/,以便再次判断该目录下面的文件 while ( (dirp = readdir(dp)) != NULL) { if (strcmp(dirp->d_name, ".") ==0 || strcmp(dirp->d_name, "..") == 0) continue; //忽略"."和".."文件 strcpy(ptr, dirp->d_name); //此时ptr指向路径名的最后,此时把文件名复制过去,相当于把文件名加到路径最后了 find(fullpath); //递归调用find函数 } // ptr[-1] = 0;这个语句,是我参考APUE上的4-7例子时写上的,仔细想想,这在这个例子中是没有用的,因为每循环完一个目录后,才会执行这条语句,但是此时的ptr不会再被用到,所以在把ptr指向的文件名连同文件名前面的斜杠(/)删除是没有意义的。 closedir(dp); }
运行结果:
与预期结果一样。源码如下:
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include "ourhdr.h"
void func(char *);
void find(char *);
int main(int argc, char **argv)
{
if (argc != 2){ printf("argument error.\n"); return(0);}
func(argv[1]);
return(0);
}
static char *fullpath;
const int pathmax=1024;
//static int n=0;
void func(char *pathname)
{
fullpath = malloc(pathmax + 1);
memset(fullpath, 0 ,pathmax+1);
strcpy(fullpath, pathname);
find(fullpath);
}
void find(char *fullpath)
{
struct stat statbuf;
DIR *dp;
struct dirent *dirp;
char *ptr;
/* printf("fullpath:%s.\t", fullpath);*/
if( lstat(fullpath, &statbuf) < 0)
{ printf("stat error.\n"); return; }
if ( S_ISDIR(statbuf.st_mode) == 0){
printf("the filename is %s\n", fullpath);
return;
}
if ( (dp = opendir(fullpath)) == NULL)
{ printf("opendir error.\n"); return; }
ptr = fullpath + strlen(fullpath);
*ptr= '/';ptr++;
*ptr = 0;
while ( (dirp = readdir(dp)) != NULL)
{
if (strcmp(dirp->d_name, ".") ==0 || strcmp(dirp->d_name, "..") == 0) continue;
strcpy(ptr, dirp->d_name);
find(fullpath);
}
// printf("%3d\tfullpath:%s\t\tptr:%s\t\n", n, fullpath, ptr);
// ptr[-1] = 0;
// printf("%3d\tfullpath:%s\t\tptr:%s\t\n", n, fullpath, ptr);
// n++;
closedir(dp);
}