getcwd – 获取当前工作目录
getcwd – 获取当前工作目录
函数介绍
getcwd
系统调用用于获取进程当前的工作目录路径。它返回一个以null结尾的字符串,表示当前目录的绝对路径名。
函数原型
#include <unistd.h>
char *getcwd(char *buf, size_t size);
功能
参数
char *buf
: 指向存储路径名的缓冲区size_t size
: 缓冲区大小(字节)
返回值
- 成功时返回指向缓冲区的指针(buf)
- 失败时返回NULL,并设置errno:
EINVAL
: size参数为0且buf非NULLERANGE
: 缓冲区太小ENOMEM
: 内存不足
相似函数
chdir()
: 改变当前工作目录fchdir()
: 通过文件描述符改变当前工作目录
示例代码
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
int main() {
char buffer[PATH_MAX];
char *result;
printf("=== Getcwd函数示例 ===\n");
// 示例1: 基本的获取当前目录操作
printf("\n示例1: 基本的获取当前目录操作\n");
// 方法1: 使用预分配的缓冲区
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
printf("当前工作目录: %s\n", buffer);
} else {
perror("获取当前目录失败");
}
// 方法2: 让系统分配内存(buf为NULL,size为0)
char *dynamic_buffer = getcwd(NULL, 0);
if (dynamic_buffer != NULL) {
printf("动态分配的当前目录: %s\n", dynamic_buffer);
free(dynamic_buffer); // 需要手动释放内存
} else {
perror("动态获取当前目录失败");
}
// 示例2: 缓冲区大小处理
printf("\n示例2: 缓冲区大小处理\n");
// 测试不同大小的缓冲区
size_t sizes[] = {10, 50, 100, PATH_MAX};
for (int i = 0; i < 4; i++) {
char small_buffer[1000]; // 足够大的缓冲区
printf("尝试使用大小为 %zu 的缓冲区: ", sizes[i]);
result = getcwd(small_buffer, sizes[i]);
if (result != NULL) {
printf("成功,目录长度: %zu 字节\n", strlen(small_buffer));
} else {
if (errno == ERANGE) {
printf("失败 - 缓冲区太小\n");
} else {
printf("失败 - %s\n", strerror(errno));
}
}
}
// 示例3: 创建测试目录并切换
printf("\n示例3: 目录切换演示\n");
// 保存原始目录
char original_dir[PATH_MAX];
if (getcwd(original_dir, sizeof(original_dir)) == NULL) {
perror("保存原始目录失败");
exit(EXIT_FAILURE);
}
printf("原始目录: %s\n", original_dir);
// 创建测试目录
const char *test_dir = "test_getcwd_dir";
if (mkdir(test_dir, 0755) == -1 && errno != EEXIST) {
perror("创建测试目录失败");
} else {
printf("创建测试目录: %s\n", test_dir);
// 切换到测试目录
if (chdir(test_dir) == -1) {
perror("切换目录失败");
} else {
printf("切换到测试目录\n");
// 获取当前目录
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
printf("切换后当前目录: %s\n", buffer);
// 验证是否正确切换
if (strstr(buffer, test_dir) != NULL) {
printf("目录切换验证成功\n");
}
}
// 在测试目录中创建子目录
const char *sub_dir = "sub_directory";
if (mkdir(sub_dir, 0755) == -1 && errno != EEXIST) {
perror("创建子目录失败");
} else {
printf("创建子目录: %s\n", sub_dir);
// 切换到子目录
if (chdir(sub_dir) == -1) {
perror("切换到子目录失败");
} else {
printf("切换到子目录\n");
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
printf("子目录路径: %s\n", buffer);
}
}
}
}
// 返回原始目录
if (chdir(original_dir) == -1) {
perror("返回原始目录失败");
} else {
printf("返回原始目录\n");
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
printf("确认当前目录: %s\n", buffer);
}
}
}
// 示例4: 错误处理演示
printf("\n示例4: 错误处理演示\n");
// 测试缓冲区太小的情况
char tiny_buffer[5];
result = getcwd(tiny_buffer, sizeof(tiny_buffer));
if (result == NULL) {
if (errno == ERANGE) {
printf("缓冲区太小错误处理正确: %s\n", strerror(errno));
} else {
printf("其他错误: %s\n", strerror(errno));
}
}
// 测试无效参数
result = getcwd(buffer, 0);
if (result == NULL) {
if (errno == EINVAL) {
printf("无效参数处理正确: %s\n", strerror(errno));
}
}
// 示例5: 实际应用场景
printf("\n示例5: 实际应用场景\n");
// 场景1: 程序配置文件定位
printf("场景1: 程序配置文件定位\n");
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
char config_path[PATH_MAX * 2];
snprintf(config_path, sizeof(config_path), "%s/.myapp/config", buffer);
printf("配置文件路径: %s\n", config_path);
// 检查配置文件是否存在
if (access(config_path, F_OK) == 0) {
printf("配置文件存在\n");
} else {
printf("配置文件不存在,将创建默认配置\n");
}
}
// 场景2: 相对路径转换为绝对路径
printf("场景2: 相对路径处理\n");
const char *relative_paths[] = {"./file.txt", "../parent_dir", "subdir/file"};
for (int i = 0; i < 3; i++) {
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
char absolute_path[PATH_MAX * 2];
snprintf(absolute_path, sizeof(absolute_path), "%s/%s", buffer, relative_paths[i]);
printf(" %s -> %s\n", relative_paths[i], absolute_path);
}
}
// 场景3: 目录操作安全检查
printf("场景3: 目录操作安全检查\n");
char current_dir[PATH_MAX];
char previous_dir[PATH_MAX];
// 保存当前目录
if (getcwd(current_dir, sizeof(current_dir)) != NULL) {
printf("当前工作目录: %s\n", current_dir);
// 执行一些目录操作
// ... 目录操作代码 ...
// 检查目录是否发生变化
if (getcwd(previous_dir, sizeof(previous_dir)) != NULL) {
if (strcmp(current_dir, previous_dir) != 0) {
printf("警告: 工作目录已改变\n");
printf("原目录: %s\n", current_dir);
printf("现目录: %s\n", previous_dir);
} else {
printf("工作目录保持不变\n");
}
}
}
// 场景4: 日志记录中的目录信息
printf("场景4: 日志记录\n");
time_t current_time = time(NULL);
result = getcwd(buffer, sizeof(buffer));
if (result != NULL) {
printf("[%s] INFO: 程序在目录 '%s' 中启动\n",
ctime(¤t_time), buffer);
}
// 示例6: 跨平台兼容性考虑
printf("\n示例6: 跨平台兼容性\n");
// 获取系统路径限制
long path_max = pathconf(".", _PC_PATH_MAX);
if (path_max == -1) {
path_max = PATH_MAX;
printf("使用默认PATH_MAX: %ld\n", path_max);
} else {
printf("系统PATH_MAX: %ld\n", path_max);
}
// 使用动态分配确保足够空间
char *safe_buffer = getcwd(NULL, 0);
if (safe_buffer != NULL) {
printf("动态分配确保安全: %s\n", safe_buffer);
printf("路径长度: %zu 字节\n", strlen(safe_buffer));
free(safe_buffer);
}
// 示例7: 性能对比测试
printf("\n示例7: 性能对比测试\n");
// 测试预分配缓冲区的性能
clock_t start = clock();
for (int i = 0; i < 10000; i++) {
getcwd(buffer, sizeof(buffer));
}
clock_t preallocated_time = clock() - start;
// 测试动态分配的性能
start = clock();
for (int i = 0; i < 10000; i++) {
char *temp = getcwd(NULL, 0);
if (temp != NULL) {
free(temp);
}
}
clock_t dynamic_time = clock() - start;
printf("预分配缓冲区 10000 次调用耗时: %f 秒\n",
((double)preallocated_time) / CLOCKS_PER_SEC);
printf("动态分配 10000 次调用耗时: %f 秒\n",
((double)dynamic_time) / CLOCKS_PER_SEC);
printf("预分配方式通常更快\n");
// 清理测试目录
printf("\n清理测试资源...\n");
if (access(test_dir, F_OK) == 0) {
if (rmdir(test_dir) == -1) {
printf("删除测试目录失败: %s\n", strerror(errno));
} else {
printf("删除测试目录完成\n");
}
}
return 0;
}