需要引用的头文件
#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;
}