如何排除正在运行的可执行文件C?目录文件遍历程序问题咨询
解决方法:排除当前运行的可执行文件
我完全理解你的困扰——遍历文件时不小心打开自身运行的可执行文件导致段错误,确实是个常见的坑。既然你已经知道程序的文件名,但不确定它的位置和初始路径,核心思路是先找到当前进程正在运行的可执行文件的唯一标识,再在遍历过程中跳过它,而不是只依赖文件名(毕竟可能存在重名文件)。
下面分平台给你具体的实现方案:
方法一:获取自身可执行文件的绝对路径
不管程序被放在哪个目录运行,先拿到它的真实绝对路径,遍历文件时对比路径,匹配就跳过。
Linux/macOS 实现
利用系统提供的/proc/self/exe符号链接(指向当前进程的可执行文件),用readlink读取它的真实路径:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <limits.h> char* get_self_executable_path() { char* exe_path = malloc(PATH_MAX); if (!exe_path) { perror("malloc failed"); return NULL; } ssize_t path_len = readlink("/proc/self/exe", exe_path, PATH_MAX); if (path_len == -1) { perror("readlink failed"); free(exe_path); return NULL; } // 确保路径以'\0'结尾 exe_path[path_len] = '\0'; return exe_path; }
遍历文件时,对每个文件调用realpath获取其绝对路径,再和自身路径对比:
char* self_path = get_self_executable_path(); // ... 遍历文件 ... char* file_abs_path = realpath(current_file_path, NULL); if (file_abs_path && strcmp(file_abs_path, self_path) == 0) { printf("Skipping self executable: %s\n", current_file_path); free(file_abs_path); continue; } free(file_abs_path); // ... 处理文件 ... free(self_path);
Windows 实现
用Windows API的GetModuleFileNameW获取当前进程的可执行文件路径:
#include <windows.h> #include <wchar.h> #include <stdlib.h> wchar_t* get_self_executable_path() { wchar_t* exe_path = malloc(MAX_PATH * sizeof(wchar_t)); if (!exe_path) { return NULL; } DWORD path_len = GetModuleFileNameW(NULL, exe_path, MAX_PATH); if (path_len == 0 || path_len == MAX_PATH) { // 路径过长或获取失败 free(exe_path); return NULL; } return exe_path; }
遍历文件时,同样获取文件的绝对路径后对比:
wchar_t* self_path = get_self_executable_path(); // ... 遍历文件 ... wchar_t file_abs_path[MAX_PATH]; if (GetFullPathNameW(current_file_path, MAX_PATH, file_abs_path, NULL) && wcscmp(file_abs_path, self_path) == 0) { wprintf(L"Skipping self executable: %s\n", current_file_path); continue; } // ... 处理文件 ... free(self_path);
方法二:通过文件唯一标识(inode/File ID)匹配
如果获取绝对路径遇到问题(比如权限限制),可以用文件的唯一系统标识来匹配,避免路径对比的麻烦。
Linux/macOS 实现
通过stat获取自身可执行文件的设备号(st_dev)和inode号(st_ino)——这两个组合能唯一标识系统中的一个文件:
#include <sys/stat.h> #include <unistd.h> int get_self_file_identity(dev_t* out_dev, ino_t* out_ino) { struct stat self_stat; if (stat("/proc/self/exe", &self_stat) == -1) { perror("stat failed"); return -1; } *out_dev = self_stat.st_dev; *out_ino = self_stat.st_ino; return 0; }
遍历文件时,对每个文件执行stat,对比设备号和inode:
dev_t self_dev; ino_t self_ino; if (get_self_file_identity(&self_dev, &self_ino) != 0) { // 处理错误 return 1; } // ... 遍历文件 ... struct stat file_stat; if (stat(current_file_path, &file_stat) == 0) { if (file_stat.st_dev == self_dev && file_stat.st_ino == self_ino) { printf("Skipping self executable: %s\n", current_file_path); continue; } } // ... 处理文件 ...
Windows 实现
用GetFileInformationByHandle获取文件的FileIndexHigh和FileIndexLow,这两个值组合是文件的唯一标识:
#include <windows.h> BOOL get_self_file_identity(LARGE_INTEGER* out_file_id) { HANDLE self_handle = CreateFileW(L"", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (self_handle == INVALID_HANDLE_VALUE) { return FALSE; } BY_HANDLE_FILE_INFORMATION file_info; BOOL result = GetFileInformationByHandle(self_handle, &file_info); if (result) { out_file_id->HighPart = file_info.nFileIndexHigh; out_file_id->LowPart = file_info.nFileIndexLow; } CloseHandle(self_handle); return result; }
遍历文件时,打开文件后获取其标识并对比:
LARGE_INTEGER self_file_id; if (!get_self_file_identity(&self_file_id)) { // 处理错误 return 1; } // ... 遍历文件 ... HANDLE file_handle = CreateFileW(current_file_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle != INVALID_HANDLE_VALUE) { BY_HANDLE_FILE_INFORMATION file_info; if (GetFileInformationByHandle(file_handle, &file_info)) { LARGE_INTEGER file_id; file_id.HighPart = file_info.nFileIndexHigh; file_id.LowPart = file_info.nFileIndexLow; if (file_id.QuadPart == self_file_id.QuadPart) { wprintf(L"Skipping self executable: %s\n", current_file_path); CloseHandle(file_handle); continue; } } CloseHandle(file_handle); } // ... 处理文件 ...
关键注意事项
- 不要只依赖文件名匹配:系统中可能存在多个同名文件,误跳过会导致程序逻辑错误。
- 处理符号链接:Linux/macOS下用
realpath,Windows下确保获取的是真实路径,避免符号链接指向自身但路径不同的情况。 - 错误处理:获取自身路径或文件标识时可能失败(比如权限不足),要做好错误兜底,避免程序崩溃。
内容的提问来源于stack exchange,提问作者Boba




