函数scandir的用法参考:Linux c目录操作函数scandir
头文件:#include <dirent.h>
定义函数:int scandir(const char *dir, struct dirent **namelist, nt (*select) (const struct dirent *), nt (*compar) (const struct dirent **, const struct dirent**));
函数说明:scandir()会扫描参数dir指定的目录文件,经由参数select指定的函数来挑选目录结构至参数namelist数组中,最后再调用参数compar指定的函数来排序namelist数组中的目录数据。每次从目录文件中读取一个目录结构后便将此结构传给参数select所指的函数, select函数若不想要将此目录结构复制到namelist数组就返回0,若select为空指针则代表选择所有的目录结构。scandir()会调用qsort()来排序数据,参数compar则为qsort()的参数,若是要排列目录名称字母则可使用alphasort(). 结构dirent定义请参考readdir()
返回值:成功则返回复制到namelist数组中的数据结构数目,有错误发生则返回-1
struct linux_dirent64 {
u64 d_ino; /* inode number 索引节点号 */
s64 d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
chard_name[0]; /* file name (null-terminated) 文件名,最长255字符 */
};
测试代码如下:
example 1
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
int main(void)
{
struct dirent **entry_list;
int count;
int i;
count = scandir("/home/book/workspace", &entry_list, 0, alphasort);
if (count < 0) {
perror("scandir");
return EXIT_FAILURE;
}
for (i = 0; i < count; i++) {
struct dirent *entry;
entry = entry_list[i];
printf("%s\n", entry->d_name);
free(entry);
}
free(entry_list);
return 0;
}
example 2
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
void make_test_data(char *path)
{
int i;
for (i = 0; i < 20; i++) {
char file[128];
sprintf(file, "file-%d", i);
creat(file, 0);
}
}
void scan(char *path, char *title, int (*sort)(const void *a, const void *b))
{
struct dirent **entry_list;
int count;
int i;
puts(title);
count = scandir(path, &entry_list, 0, sort);
if (count < 0) {
perror("scandir");
return EXIT_FAILURE;
}
for (i = 0; i < count; i++) {
struct dirent *entry;
entry = entry_list[i];
printf("%s\n", entry->d_name);
free(entry);
}
printf("\n");
free(entry_list);
}
int main(void)
{
char *path = ".";
make_test_data(path);
scan(path, "alphasort: ", alphasort);
scan(path, "versionsort: ", versionsort);
return 0;
}
example 3
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
int filter(const struct dirent *entry)
{
return entry->d_name[0] == 'a';
}
int main(void)
{
struct dirent **entry_list;
int count;
int i;
count = scandir("/usr/include", &entry_list, filter, alphasort);
if (count < 0) {
perror("scandir");
return EXIT_FAILURE;
}
for (i = 0; i < count; i++) {
struct dirent *entry;
entry = entry_list[i];
printf("%s\n", entry->d_name);
free(entry);
}
free(entry_list);
return 0;
}
对文件操作我们经常和这个stat结构体打交道:linux-3.4.2\include\asm-generic\Stat.h
这个结构体就把文件的所有信息都包含在其中了,其中很重要的一个成员是:unsigned intst_mode;/* File mode. */
这个成员选项定义 \linux-3.4.2\include\linux\Stat.h中:
S_ISLNK(st_mode):是否是一个连接.
S_ISREG是否是一个常规文件.
S_ISDIR是否是一个目录
S_ISCHR是否是一个字符设备
S_ISBLK是否是一个块设备
S_ISFIFO是否 是一个FIFO文件
S_ISSOCK是否是一个SOCKET文件
例子一:
下面我们开发一个小程序,这个程序有一个参数.如果这个参数是一个文件名,我们输出这个文件的大小和最后修改的时间,如果是一个目录我们输出这个目录下所有文件的大小和修改时间.
代码如下:
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <time.h>
static int get_file_size_time(const char *filename) {
struct stat statbuf;
if (stat(filename, &statbuf) == -1) {
printf("Get stat on %s Error:%s\n",
filename, strerror(errno));
return (-1);
}
if (S_ISDIR(statbuf.st_mode))return (1);
if (S_ISREG(statbuf.st_mode))
printf("%s size:%ld bytes\tmodified at %s",
filename, statbuf.st_size, ctime(&statbuf.st_mtime));
return (0);
}
int main(int argc, char **argv) {
DIR *dirp;
struct dirent *direntp;
int stats;
char buf[80];
if (argc != 2) {
printf("Usage:%s filename\n\a", argv[0]);
exit(1);
}
if (((stats = get_file_size_time(argv[1])) == 0) || (stats == -1))exit(1);
if ((dirp = opendir(argv[1])) == NULL) {
printf("Open Directory %s Error:%s\n",
argv[1], strerror(errno));
exit(1);
}
while ((direntp = readdir(dirp)) != NULL){
sprintf(buf,"%s/%s",argv[1],direntp->d_name);
if (get_file_size_time(buf) == -1)break;
}
closedir(dirp);
exit(1);
}
例子二:
测试检测出来的文件,分辨它是目录还是普通文件
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
struct dirent **namelist;
struct stat tStat;
int n;
char strTmp[256];
n = scandir("../", &namelist, NULL, alphasort);
if (n < 0)
perror("scandir");
else {
while (n--) {
snprintf(strTmp, 256, "%s/%s", "../", namelist[n]->d_name);
strTmp[255] = '\0';
if ((stat(strTmp, &tStat) == 0))
{
if(S_ISDIR(tStat.st_mode))
{
printf("%s:is a dir\n", namelist[n]->d_name);
}
else if(S_ISREG(tStat.st_mode))
{
printf("%s:is a file\n", namelist[n]->d_name);
}
else
{
printf("%s:unknow2\n", namelist[n]->d_name);
}
}
free(namelist[n]);
}
free(namelist);
}
return 0;
}