在 Windows 平台獲取目錄下所有文件名,最快原型用 system("dir /b") 重定向到臨時文件再讀取;生產代碼應使用 FindFirstFile/FindNextFile Windows API。本文對比兩種方案的代碼、優缺點、避坑指南。
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main() {
const char *target_dir = "E:\\Ock\\DirSave";
const char *tmp_file = "D:\\buf.tmp";
// 1. 執行 dir /b 只輸出文件名,重定向到臨時文件
char cmd[512];
snprintf(cmd, sizeof(cmd), "dir /b \"%s\" > \"%s\"", target_dir, tmp_file);
if (system(cmd) != 0) {
fprintf(stderr, "dir 命令失敗\n");
return 1;
}
// 2. 讀取臨時文件
FILE *fp = fopen(tmp_file, "r");
if (!fp) { perror(tmp_file); return 1; }
char line[260];
char *last = NULL;
while (fgets(line, sizeof(line), fp)) {
// 去除換行符
line[strcspn(line, "\r\n")] = '\0';
if (line[0]) last = _strdup(line); // 保存最後一行
}
fclose(fp);
// 3. 刪除臨時文件
char del_cmd[512];
snprintf(del_cmd, sizeof(del_cmd), "del /q \"%s\"", tmp_file);
system(del_cmd);
if (last) {
printf("最後一個文件: %s\n", last);
free(last);
} else {
puts("目錄為空");
}
return 0;
}
dir /b:裸格式,無表頭/摘要/日期,僅文件名,適合解析。> file:Shell 重定向,覆蓋寫入。del /q:安靜刪除,無確認提示。#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void list_files(const TCHAR *dir) {
WIN32_FIND_DATA ffd;
TCHAR search_path[MAX_PATH];
// 構建搜索模式:目錄\*
_stprintf_s(search_path, MAX_PATH, _T("%s\\*"), dir);
HANDLE hFind = FindFirstFile(search_path, &ffd);
if (hFind == INVALID_HANDLE_VALUE) {
_tprintf(_T("FindFirstFile 失敗 (%lu)\n"), GetLastError());
return;
}
do {
// 跳過 . 和 ..
if (_tcscmp(ffd.cFileName, _T(".")) == 0 ||
_tcscmp(ffd.cFileName, _T("..")) == 0)
continue;
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
_tprintf(_T("[DIR] %s\n"), ffd.cFileName);
} else {
// 文件大小:組合高低 32 位
ULONGLONG size = ((ULONGLONG)ffd.nFileSizeHigh << 32) | ffd.nFileSizeLow;
_tprintf(_T("%s %llu bytes\n"), ffd.cFileName, size);
}
} while (FindNextFile(hFind, &ffd));
DWORD err = GetLastError();
FindClose(hFind);
if (err != ERROR_NO_MORE_FILES)
_tprintf(_T("FindNextFile 錯誤 (%lu)\n"), err);
}
int main() {
list_files(_T("E:\\Ock\\DirSave"));
return 0;
}
\\\\?\\。FILE_ATTRIBUTE_DIRECTORY 遞歸調用)。#include <dirent.h>
#include <stdio.h>
void list_dir_posix(const char *path) {
DIR *d = opendir(path);
if (!d) { perror(path); return; }
struct dirent *ent;
while ((ent = readdir(d))) {
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
printf("%s\n", ent->d_name);
}
closedir(d);
}
| 維度 | system+dir | Windows API | dirent.h |
|---|---|---|---|
| 代碼量 | 極少 | 中等 | 極少 |
| 性能 | 低 (進程創建+IO) | 高 (內核遍歷) | 高 |
| 信息豐富度 | 僅文件名 | 完整屬性 | 文件名+類型(d_type) |
| Unicode/長路徑 | 麻煩 | 原生支持 | 原生支持 |
| 適用場景 | 測試腳本、一次性任務 | Windows 生產代碼 | 跨平台庫/工具 |
int list_dir(const char*, FileCallback, void*),內部 `#ifdef _WIN32` 分派。\\\\?\\ 前綴。GetLastError(),區分「無更多文件」與真實錯誤。從「借用 Shell 一鍵搞定」到「調用系統 API 精準控制」,是 C 開發者從腳本思維向系統編程思維進化的標誌性一步。