当前位置: 首页 > news >正文

chdir系统调用及示例

chdir - 改变当前工作目录

函数介绍

chdir系统调用用于改变进程的当前工作目录。成功调用后,进程的所有相对路径操作都基于新的工作目录进行。

函数原型

#include <unistd.h>int chdir(const char *path);

功能

改变进程当前工作目录到指定路径。

参数

  • const char *path: 目标目录的路径名(可以是相对路径或绝对路径)

返回值

  • 成功时返回0
  • 失败时返回-1,并设置errno:
    • EACCES: 权限不足
    • EIO: I/O错误
    • ELOOP: 符号链接循环
    • ENAMETOOLONG: 路径名过长
    • ENOENT: 目录不存在
    • ENOTDIR: 路径不是目录
    • EROFS: 目录在只读文件系统上

相似函数

  • fchdir(): 通过文件描述符改变当前工作目录
  • getcwd(): 获取当前工作目录

示例代码

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <limits.h>int main() {char buffer[PATH_MAX];char original_dir[PATH_MAX];printf("=== Chdir函数示例 ===\n");// 保存原始目录if (getcwd(original_dir, sizeof(original_dir)) == NULL) {perror("获取原始目录失败");exit(EXIT_FAILURE);}printf("原始工作目录: %s\n", original_dir);// 示例1: 基本的目录切换操作printf("\n示例1: 基本的目录切换操作\n");// 切换到根目录if (chdir("/") == -1) {perror("切换到根目录失败");} else {printf("成功切换到根目录\n");if (getcwd(buffer, sizeof(buffer)) != NULL) {printf("当前目录: %s\n", buffer);}}// 切换回原始目录if (chdir(original_dir) == -1) {perror("返回原始目录失败");} else {printf("成功返回原始目录\n");if (getcwd(buffer, sizeof(buffer)) != NULL) {printf("当前目录: %s\n", buffer);}}// 示例2: 创建测试环境printf("\n示例2: 创建测试环境\n");// 创建测试目录结构const char *base_dir = "test_chdir_base";const char *sub_dir1 = "test_chdir_base/subdir1";const char *sub_dir2 = "test_chdir_base/subdir2";const char *deep_dir = "test_chdir_base/subdir1/deepdir";// 创建目录if (mkdir(base_dir, 0755) == -1 && errno != EEXIST) {perror("创建基础目录失败");} else {printf("创建基础目录: %s\n", base_dir);}if (mkdir(sub_dir1, 0755) == -1 && errno != EEXIST) {perror("创建子目录1失败");} else {printf("创建子目录1: %s\n", sub_dir1);}if (mkdir(sub_dir2, 0755) == -1 && errno != EEXIST) {perror("创建子目录2失败");} else {printf("创建子目录2: %s\n", sub_dir2);}if (mkdir(deep_dir, 0755) == -1 && errno != EEXIST) {perror("创建深层目录失败");} else {printf("创建深层目录: %s\n", deep_dir);}// 在目录中创建测试文件int fd = open("test_chdir_base/test_file.txt", O_CREAT | O_WRONLY, 0644);if (fd != -1) {const char *content = "Test file content for chdir demonstration";write(fd, content, strlen(content));close(fd);printf("创建测试文件: test_chdir_base/test_file.txt\n");}// 示例3: 绝对路径和相对路径切换printf("\n示例3: 绝对路径和相对路径切换\n");// 使用绝对路径切换char absolute_path[PATH_MAX * 2];snprintf(absolute_path, sizeof(absolute_path), "%s/%s", original_dir, base_dir);printf("使用绝对路径切换: %s\n", absolute_path);if (chdir(absolute_path) == -1) {perror("使用绝对路径切换失败");} else {printf("绝对路径切换成功\n");if (getcwd(buffer, sizeof(buffer)) != NULL) {printf("当前目录: %s\n", buffer);}}// 使用相对路径切换到子目录printf("使用相对路径切换到子目录1\n");if (chdir("subdir1") == -1) {perror("切换到子目录1失败");} else {printf("切换到子目录1成功\n");if (getcwd(buffer, sizeof(buffer)) != NULL) {printf("当前目录: %s\n", buffer);}}// 使用相对路径返回上级目录printf("使用相对路径返回上级目录\n");if (chdir("..") == -1) {perror("返回上级目录失败");} else {printf("返回上级目录成功\n");if (getcwd(buffer, sizeof(buffer)) != NULL) {printf("当前目录: %s\n", buffer);}}// 切换到深层目录printf("切换到深层目录\n");if (chdir("subdir1/deepdir") == -1) {perror("切换到深层目录失败");} else {printf("切换到深层目录成功\n");if (getcwd(buffer, sizeof(buffer)) != NULL) {printf("当前目录: %s\n", buffer);}}// 使用多个..返回printf("使用多个..返回原始目录\n");if (chdir("../../..") == -1) {perror("多级返回失败");} else {printf("多级返回成功\n");if (getcwd(buffer, sizeof(buffer)) != NULL) {printf("当前目录: %s\n", buffer);}}// 示例4: 目录切换的副作用演示printf("\n示例4: 目录切换的副作用演示\n");// 切换到测试目录if (chdir(base_dir) == -1) {perror("切换到测试目录失败");} else {printf("切换到测试目录\n");// 在当前目录创建文件fd = open("created_in_cwd.txt", O_CREAT | O_WRONLY, 0644);if (fd != -1) {const char *file_content = "File created in current working directory";write(fd, file_content, strlen(file_content));close(fd);printf("在当前目录创建文件: created_in_cwd.txt\n");}// 列出当前目录文件printf("当前目录文件:\n");system("ls -la");// 切换目录后再次查看if (chdir("subdir1") == -1) {perror("切换到子目录失败");} else {printf("\n切换到子目录后:\n");system("ls -la");}}// 返回原始目录if (chdir(original_dir) == -1) {perror("返回原始目录失败");}// 示例5: 错误处理演示printf("\n示例5: 错误处理演示\n");// 尝试切换到不存在的目录if (chdir("/nonexistent/directory") == -1) {printf("切换到不存在的目录: %s\n", strerror(errno));}// 尝试切换到文件而不是目录if (chdir("/etc/passwd") == -1) {printf("切换到文件而非目录: %s\n", strerror(errno));}// 尝试切换到没有权限的目录if (chdir("/root") == -1) {printf("切换到无权限目录: %s\n", strerror(errno));}// 尝试使用过长的路径名char long_path[PATH_MAX + 100];memset(long_path, 'a', sizeof(long_path) - 1);long_path[sizeof(long_path) - 1] = '\0';if (chdir(long_path) == -1) {printf("使用过长路径名: %s\n", strerror(errno));}// 示例6: 实际应用场景printf("\n示例6: 实际应用场景\n");// 场景1: 程序初始化时切换到工作目录printf("场景1: 程序工作目录设置\n");const char *work_dir = "/tmp";if (chdir(work_dir) == -1) {printf("无法切换到工作目录 %s: %s\n", work_dir, strerror(errno));printf("使用当前目录作为工作目录\n");} else {printf("成功切换到工作目录: %s\n", work_dir);}// 场景2: 备份脚本中的目录操作printf("场景2: 备份操作模拟\n");char backup_dir[PATH_MAX];snprintf(backup_dir, sizeof(backup_dir), "%s/backup_test", original_dir);// 创建备份目录if (mkdir(backup_dir, 0755) == -1 && errno != EEXIST) {perror("创建备份目录失败");} else {printf("创建备份目录: %s\n", backup_dir);// 切换到备份目录if (chdir(backup_dir) == -1) {perror("切换到备份目录失败");} else {printf("切换到备份目录进行操作\n");// 模拟备份操作system("echo 'Backup operation in progress...' > backup.log");system("date >> backup.log");printf("备份操作记录已保存\n");}}// 场景3: 构建系统中的目录管理printf("场景3: 构建系统目录管理\n");struct {const char *dir_name;const char *purpose;} build_dirs[] = {{"src", "源代码目录"},{"include", "头文件目录"},{"lib", "库文件目录"},{"bin", "可执行文件目录"},{"obj", "目标文件目录"}};// 切换到基础目录if (chdir(base_dir) == -1) {perror("切换到基础目录失败");} else {printf("在 %s 中创建构建目录结构:\n", base_dir);for (int i = 0; i < 5; i++) {if (mkdir(build_dirs[i].dir_name, 0755) == -1 && errno != EEXIST) {printf("  创建 %s 失败: %s\n", build_dirs[i].dir_name, strerror(errno));} else {printf("  创建 %s (%s)\n", build_dirs[i].dir_name, build_dirs[i].purpose);}}}// 场景4: Web服务器目录切换printf("场景4: Web服务器目录安全\n");const char *web_root = "/var/www";printf("Web服务器尝试切换到根目录: %s\n", web_root);// 检查目录是否存在和可访问if (access(web_root, F_OK) == 0) {if (access(web_root, R_OK | X_OK) == 0) {printf("目录存在且可访问\n");// 在实际应用中会进行chdir操作} else {printf("目录存在但权限不足\n");}} else {printf("目录不存在或无法访问\n");}// 示例7: 目录切换的安全考虑printf("\n示例7: 目录切换的安全考虑\n");// 保存原始目录文件描述符(用于安全返回)int original_fd = open(".", O_RDONLY);if (original_fd != -1) {printf("保存原始目录文件描述符: %d\n", original_fd);// 执行目录切换if (chdir(base_dir) == -1) {perror("切换目录失败");} else {printf("切换到测试目录\n");// 执行一些操作system("pwd");// 使用文件描述符安全返回if (fchdir(original_fd) == -1) {perror("使用文件描述符返回失败");} else {printf("使用文件描述符安全返回原始目录\n");system("pwd");}}close(original_fd);}// 示例8: 相对路径解析演示printf("\n示例8: 相对路径解析\n");if (chdir(base_dir) == -1) {perror("切换到测试目录失败");} else {printf("当前目录: ");system("pwd");// 相对路径解析示例struct {const char *relative_path;const char *description;} paths[] = {{".", "当前目录"},{"..", "上级目录"},{"./subdir1", "当前目录下的子目录"},{"../subdir2", "上级目录下的另一个子目录"},{"subdir1/./deepdir", "带.的路径"},{"subdir1/../subdir2", "带..的路径"}};for (int i = 0; i < 6; i++) {printf("路径 '%s' (%s):\n", paths[i].relative_path, paths[i].description);// 保存当前位置int save_fd = open(".", O_RDONLY);if (save_fd != -1) {// 尝试切换if (chdir(paths[i].relative_path) == 0) {printf("  切换成功: ");system("pwd");// 返回原位置if (fchdir(save_fd) == -1) {perror("  返回失败");}} else {printf("  切换失败: %s\n", strerror(errno));}close(save_fd);}printf("\n");}}// 返回原始目录if (chdir(original_dir) == -1) {perror("最终返回原始目录失败");}// 清理测试资源printf("\n清理测试资源...\n");// 删除测试文件char test_file_path[PATH_MAX * 2];snprintf(test_file_path, sizeof(test_file_path), "%s/%s/created_in_cwd.txt", original_dir, base_dir);if (access(test_file_path, F_OK) == 0) {unlink(test_file_path);printf("删除测试文件\n");}// 删除备份目录和文件char backup_file_path[PATH_MAX * 2];snprintf(backup_file_path, sizeof(backup_file_path), "%s/backup.log", backup_dir);if (access(backup_file_path, F_OK) == 0) {unlink(backup_file_path);}if (access(backup_dir, F_OK) == 0) {rmdir(backup_dir);printf("删除备份目录\n");}// 删除构建目录if (chdir(base_dir) == 0) {for (int i = 0; i < 5; i++) {rmdir(build_dirs[i].dir_name);}chdir(original_dir);}// 删除测试目录结构char deep_dir_path[PATH_MAX * 2];snprintf(deep_dir_path, sizeof(deep_dir_path), "%s/%s", original_dir, deep_dir);if (access(deep_dir_path, F_OK) == 0) {rmdir(deep_dir_path);}char subdir1_path[PATH_MAX * 2];snprintf(subdir1_path, sizeof(subdir1_path), "%s/%s", original_dir, sub_dir1);if (access(subdir1_path, F_OK) == 0) {rmdir(subdir1_path);}char subdir2_path[PATH_MAX * 2];snprintf(subdir2_path, sizeof(subdir2_path), "%s/%s", original_dir, sub_dir2);if (access(subdir2_path, F_OK) == 0) {rmdir(subdir2_path);}char test_file[PATH_MAX * 2];snprintf(test_file, sizeof(test_file), "%s/%s/test_file.txt", original_dir, base_dir);if (access(test_file, F_OK) == 0) {unlink(test_file);}char base_dir_path[PATH_MAX * 2];snprintf(base_dir_path, sizeof(base_dir_path), "%s/%s", original_dir, base_dir);if (access(base_dir_path, F_OK) == 0) {rmdir(base_dir_path);printf("删除测试目录结构完成\n");}return 0;
}
http://www.dtcms.com/a/318486.html

相关文章:

  • 【C/C++】形参、实参相关内容整理
  • 零基础-动手学深度学习-8.7. 通过时间反向传播
  • Spring_事务
  • 国产3D大型装配设计新突破①:图纸打开设计双加速 | 中望3D 2026
  • C语言的数组与字符串练习题2
  • 如何快速翻译PPT中的文字(或简繁体转换)
  • 【51单片机2个独立按键2个独立数码管静态显示内容自定】2022-10-22
  • Perforce P4 Plan - DevOps实时规划工具
  • 指挥中心自动化的演变
  • 无人机遥控器波特率技术解析
  • 前端开发_怎么禁止用户复制内容
  • 计算机网络:如何判断B或者C类IP地址是否划分了子网
  • 设备 AI 知识库如何提升管理效率?实测分享
  • 【STM32U385RG 测评】基于VSCode的STM32开发环境搭建
  • 认识河豚毒素!剧毒神经毒素详解!
  • 向量数据库基础夯实:相关概念的详细介绍
  • 淘宝/天猫商品详情API详解(tb.item_get)
  • 一文读懂:什么是CLIP
  • 分布式存储 Ceph 的演进经验 · SOSP 2019
  • 【Web安全】csrf、ssrf和xxe的区别
  • GPT-OSS-20B vs Qwen3-14B 全面对比测试
  • 【大模型系列】gpt-oss系列模型初探
  • ACL 2025 Oral|Evaluation Agent:面向视觉生成模型的高效可提示的评估框架
  • 服务器重启后mysql5.7启动失败问题
  • MySql_忘记了root密码怎么办
  • win服务器系统10060问题解决
  • Kali Linux虚拟机安装和中文配置详细教程(2025版)
  • Sklearn 机器学习 数据聚类 DBSCAN聚类算法的异常点
  • MicrochipSam9x60 PIO寄存器操作流程
  • TypeScript 元组类型精简知识点