You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何排除正在运行的可执行文件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获取文件的FileIndexHighFileIndexLow,这两个值组合是文件的唯一标识:

#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

火山引擎 最新活动