在 Debian(或者说 Linux 下 C/C++ 编程)里,readdir() 本身不会保证任何顺序,它返回的是目录项在底层文件系统中的顺序(通常近似于创建顺序或哈希顺序),所以需要你自己排序。
下面给你几种常见做法,从“最常用”到“底层”。
opendir() + readdir() 读取所有目录项qsort() 排序#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int compare(const void *a, const void *b) {
return strcmp(*(const char **)a, *(const char **)b);
}
int main() {
DIR *dir = opendir(".");
if (!dir) return 1;
struct dirent *entry;
char **names = NULL;
int count = 0;
while ((entry = readdir(dir))) {
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
continue;
names = realloc(names, sizeof(char*) * (count + 1));
names[count++] = strdup(entry->d_name);
}
closedir(dir);
qsort(names, count, sizeof(char*), compare);
for (int i = 0; i < count; i++) {
printf("%s\n", names[i]);
free(names[i]);
}
free(names);
}
✅ 优点
如果你希望:
file1, file2, file10
而不是:
file1, file10, file2
可以使用 strverscmp()(GNU 扩展):
#define _GNU_SOURCE
#include <string.h>
int compare(const void *a, const void *b) {
return strverscmp(*(const char **)a, *(const char **)b);
}
⚠️ 仅在 glibc(Debian 默认)可用
#include <sys/stat.h>
int compare(const void *a, const void *b) {
struct stat sa, sb;
stat(*(const char **)a, &sa);
stat(*(const char **)b, &sb);
return sa.st_mtime - sb.st_mtime;
}
scandir() 自动帮你排序:
#include <dirent.h>
struct dirent **namelist;
int n = scandir(".", &namelist, NULL, alphasort);
for (int i = 0; i < n; i++) {
printf("%s\n", namelist[i]->d_name);
free(namelist[i]);
}
free(namelist);
✅ 简单
❌ 内存占用大,目录很大时不推荐
如果只是命令行:
ls -1 | sort
ls -1v # 自然排序
ls -lt # 按时间
| 方式 | 是否排序 | 推荐度 |
|---|---|---|
| readdir | ❌ | ⭐⭐⭐⭐(配合 qsort) |
| scandir | ✅ | ⭐⭐⭐ |
| readdir + qsort | ✅ | ⭐⭐⭐⭐⭐ |
如果你能告诉我:
我可以给你更精确的代码。