需要引用的頭文件
#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 為 0022mode_t old_umask = umask(0022);// 創建目錄const char *pathname = "/home/user/newdir";mode_t mode = 0777; // 設置目錄權限為 777if (mkdir(pathname, mode) != 0) {perror("mkdir failed");return 1;}printf("Successfully created directory: %s\n", pathname);// 恢復舊的 umaskumask(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 dirARGS_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;
}