一、目录扫描函数及其相关结构
1. struct dirent *readdir(DIR *dp);
2. DIR *opendir(const char *name);
4. int closedir(DIR *dp);
5. void rewinddir(DIR *dp);
6. void seekdir(DIR *dp,long loc);
7. long telldir(DIR *dp);
8. int mkdir(const char *pathname, mode_t mode);
9. int rmdir(const char *pathname);
10. int chmod(const char *path, mode_t mode);//改变文件或目录的属性
struct __dirstream
{
void *__fd;
char *__data;
int __entry_data;
char *__ptr;
int __entry_ptr;
size_t __allocation;
size_t __size;
__libc_lock_define (, __lock)
};
typedef struct __dirstream DIR;
struct dirent
{
long d_ino; /* inode number索引节点号 */
off_t d_off; /* offset to this dirent在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name文件名长 */
unsigned char d_type; /* the type of d_name文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated)文件名,最长255字符 */
}
从上述定义也能够看出来,dirent结构体存储的关于文件的信息很少,所以dirent同样也是起着一个索引的作用,如果想获得类似ls -l那种效果的文件信息,必须要靠stat函数了。
通过readdir函数读取到的文件名存储在结构体dirent的d_name成员中,而函数
int stat(const char *file_name, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *path, struct stat *buf);
的作用就是获取文件名为d_name的文件的详细信息,存储在stat结构体中。以下为stat结构体的定义:
struct stat
{
mode_t st_mode; //文件访问权限
ino_t st_ino; //索引节点号
dev_t st_dev; //文件使用的设备号
dev_t st_rdev; //设备文件的设备号
nlink_t st_nlink; //文件的硬连接数
uid_t st_uid; //所有者用户识别号
gid_t st_gid; //组识别号
off_t st_size; //以字节为单位的文件容量
time_t st_atime; //最后一次访问该文件的时间
time_t st_mtime; //最后一次修改该文件的时间
time_t st_ctime; //最后一次改变该文件状态的时间
blksize_t st_blksize; //包含该文件的磁盘块的大小
blkcnt_t st_blocks; //该文件所占的磁盘块
};
如果想要获取某目录下(比如a目下/a/b)b文件的详细信息,分为以下3步(详情见下面例子):
1.opendir函数打开目录a,返回指向目录a的DIR结构体c。
2.readdir( c)函数读取目录a下所有文件(包括目录),返回指向目录a下所有文件的dirent结构体d。
3.遍历d,调用stat(d->name,stat *e)来获取每个文件的详细信息,存储在stat结构体e中。
二、打印目录下所有文件及目录的程序
#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
//dir为目录名,depth为空格个数
void printdir(char *dir, int depth)
{
DIR* dp;
struct dirent* entry;
struct stat statbuf;
if(NULL == (dp = opendir(dir))) //打开dir目录
{
fprintf(stderr, "Can`t open directory %s\n", dir);
return ;
}
chdir(dir);//cd dir
while(NULL != (entry = readdir(dp)))
{
lstat(entry->d_name, &statbuf); //获取文件名信息
if (S_ISDIR(statbuf.st_mode)) { //如果为目录
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)//如果为当前或上一目录,则读取下一个文件
continue;
printf("%*s%s/\n", depth, "", entry->d_name);
printdir(entry->d_name,depth+4); //为空格个数
} else
printf("%*s%s\n", depth, "", entry->d_name);
}
chdir(".."); //返回上一路径
closedir(dp); //关闭目录
}
int main(void)
{
char topdir[32] = {0};
printf("plese input scan of Directory: ");
scanf("%s", topdir);
printf("Directory scan of %s\n", topdir);
printdir(topdir, 0);
printf("done.\n");
return 0;
}
a目录下的目录及文件为:
[root@localhost a]# ls
1.c 2.c 3.txt b
[root@localhost b]# ls
a.c b.c c c.c
[root@localhost c]# ls
e.c f.c
扫描a目录,结果为:
[root@localhost for_test]# ./a.out
plese input scan of Directory: ./a
111:./a 111Directory scan of ./a
b/
c.c
c/
e.c
f.c
b.c
a.c
3.txt
2.c
1.c
done.
能扫描目录,当然就能对目录下的文件或目录进行操作了!