Linux C 目录基本操作

发布于:2025-06-25 ⋅ 阅读:(14) ⋅ 点赞:(0)

需要引用的头文件

#include <unistd.h>

unistd.h 为程序提供了对POSIX操作系统API的访问接口,主要用于提供与系统调用相关的功能。

char *getcwd(char *buf, size_t size);

用于获取当前工作目录(Current Working Directory)的绝对路径。

参数
buf: 指向存放当放当前目录的数组
size: 数组的大小
返回值
成功:返回包含当前工作目录的字符串。如果buf不为NULL,即返回buf。
失败:返回NULL,并设置errno

示例:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    char *buf = NULL; // 使用动态分配
    char *cwd = getcwd(buf, 0); // 0 表示动态分配
    if (cwd == NULL) {
        perror("getcwd failed");
        return 1;
    }
    printf("Current working directory: %s\n", cwd);
    free(cwd); // 释放动态分配的内存
    return 0;
}

运行该程序后,会输出当前工作目录的绝对路径。

如果传入的 buf 为 NULL ,且 size 为 0,则 getcwd 会调用 malloc 申请合适大小的内存空间,填入当前工作目录的绝对路径,然后返回 malloc 申请的空间的地址。
注意: getcwd 不负责 free 申请的空间, free 是调用者的职责。

int chdir(const char *path);

chdir 函数可以改变当前工作目录。
参数
path: 改变后的路径。 

  • 路径可以是绝对路径(从根目录开始),也可以是相对路径(相对于当前工作目录)。

返回值
成功:返回0。
失败:返回-1,并设置errno。

chdir 函数用于将当前进程的工作目录切换到指定的目录。当前工作目录是指当前进程在文件系统中的位置,类似于在命令行中使用 cd 命令的效果。改变工作目录后,所有相对路径的文件操作都将基于新的工作目录进行。

示例:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    // 尝试切换到指定目录
    if (chdir("/home/user/project") != 0) {
        perror("chdir failed");
        return 1;
    }
    printf("Successfully changed directory to /home/user/project\n");

    // 获取当前工作目录并打印
    char *buf = NULL; // 使用动态分配
    char *cwd = getcwd(buf, 0); // 0 表示动态分配
    if (cwd == NULL) {
        perror("getcwd failed");
        return 1;
    }
    printf("Current working directory: %s\n", cwd);
    free(cwd); // 释放动态分配的内存
    return 0;
}

注意事项

  • 权限问题

    • 调用进程需要有足够的权限才能切换到指定目录。如果目标目录的权限设置不允许当前用户访问,则会返回 EACCES 错误。

  • 线程安全性

    • chdir 函数是线程安全的,可以在多线程程序中安全使用。但是,需要注意的是,改变工作目录会影响整个进程,包括所有线程。

int mkdir(const char *pathname, mode_t mode);

mkdir 函数用于创建一个新的目录。如果指定的路径已经存在,或者路径中某个组件不存在或不是目录,函数将失败并返回相应的错误码。

参数
pathname: 要创建目录的路径
mode: 目录的权限位,会受文件创建掩码umask的影响,实际的权限为(mode & ~umask
& 0777)

umask(用户文件创建掩码,User File Creation Mask)是一个用于控制新创建文件和目录默认权限的机制。它通过限制文件和目录的权限,确保新创建的文件和目录不会被赋予过于宽松的权限。

可以通过在终端中键入 umask 来查看默认掩码值

假设 umask 设置为 0022,那么:

  • 对于文件:

    最终权限=0666&∼0022=0666&0755=0644

    即文件的最终权限为 0644(所有者有读写权限,组内用户和其他用户有读权限)。

返回值
成功:返回0
失败:返回-1,并设置errno

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    // 设置 umask 为 0022
    mode_t old_umask = umask(0022);

    // 创建目录
    const char *pathname = "/home/user/newdir";
    mode_t mode = 0777; // 设置目录权限为 777
    if (mkdir(pathname, mode) != 0) {
        perror("mkdir failed");
        return 1;
    }
    printf("Successfully created directory: %s\n", pathname);

    // 恢复旧的 umask
    umask(old_umask);

    return 0;
}


int rmdir(const char *pathname);

rmdir 函数用于删除一个空目录。如果目录不为空(即目录中包含文件或其他目录),rmdir 将无法删除该目录,并返回 EEXIST 错误。
参数
pathname: 要删除的目录
返回值
成功:返回0
失败:返回-1,并设置errno

#include <func.h>
int main(int argc, char* argv[]) {
    // ./rmdir dir
    ARGS_CHECK(argc, 2);
    int ret = rmdir(argv[1]);
    // 注意:rmdir 只能删除空目录
    ERROR_CHECK(ret, -1, "rmdir");
    return 0;
}
  • rmdir 函数用于删除空目录。

  • 如果目录不为空,需要先删除目录中的内容,再删除目录。

如果该目录非空,需要递归删除目录中的内容,实现如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>

int remove_directory(const char *pathname) {
    DIR *dir;
    struct dirent *entry;
    char path[PATH_MAX];
    int ret = 0;

    // 打开目录
    dir = opendir(pathname);
    if (dir == NULL) {
        perror("opendir failed");
        return -1;
    }

    // 遍历目录中的所有条目
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue; // 跳过 "." 和 ".."
        }

        // 构造完整的路径
        snprintf(path, sizeof(path), "%s/%s", pathname, entry->d_name);

        // 检查是否为目录
        struct stat statbuf;
        if (stat(path, &statbuf) == -1) {
            perror("stat failed");
            ret = -1;
            break;
        }

        if (S_ISDIR(statbuf.st_mode)) {
            // 递归删除子目录
            if (remove_directory(path) == -1) {
                ret = -1;
                break;
            }
        } else {
            // 删除文件
            if (unlink(path) == -1) {
                perror("unlink failed");
                ret = -1;
                break;
            }
        }
    }

    // 关闭目录
    closedir(dir);

    // 删除当前目录
    if (rmdir(pathname) == -1) {
        perror("rmdir failed");
        return -1;
    }

    return ret;
}

int main() {
    const char *pathname = "/home/user/newdir";

    // 尝试删除目录
    if (remove_directory(pathname) != 0) {
        return 1;
    }
    printf("Successfully removed directory: %s\n", pathname);

    return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到