Linux C如何判斷文件類型?


通過stat()讀取指定文件狀態, 然后通過宏測試struct stat的st_mode成員得到文件類型.
stat函數有3個版本, 它們的區別是stat參數需要一個文件路徑, fstat需要一個已打開文件描述符, lstat不跟隨符號鏈接(當文件是符號鏈接時, 獲得符號鏈接自身文件狀態, 而不是獲得其指向的文件狀態)

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

int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);

struct stat定義

struct stat {
   dev_t     st_dev;         /* ID of device containing file */
   ino_t     st_ino;         /* Inode number */
   mode_t    st_mode;        /* File type and mode */
   nlink_t   st_nlink;       /* Number of hard links */
   uid_t     st_uid;         /* User ID of owner */
   gid_t     st_gid;         /* Group ID of owner */
   dev_t     st_rdev;        /* Device ID (if special file) */
   off_t     st_size;        /* Total size, in bytes */
   blksize_t st_blksize;     /* Block size for filesystem I/O */
   blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */

   /* Since Linux 2.6, the kernel supports nanosecond
      precision for the following timestamp fields.
      For the details before Linux 2.6, see NOTES. */

   struct timespec st_atim;  /* Time of last access */
   struct timespec st_mtim;  /* Time of last modification */
   struct timespec st_ctim;  /* Time of last status change */

#define st_atime st_atim.tv_sec      /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};

可以通過宏確定文件類型

文件類型
S_ISREG() 普通文件
S_ISDIR() 目錄文件
S_ISCHR() 字符特殊文件
S_ISBLK() 塊特殊文件
S_ISFIFO() 管道或FIFO
S_ISLNK() 符號鏈接
S_ISSOCK() 套接字

也可以通過宏確定IPC(進程間通信)對象類型

文件類型
S_TYPEISMQ() 消息隊列
S_TYPEISSEM() 信號量
S_TYPEISSHM() 共享內存對象

文件類型宏測試實質是按位與運算, 我們也可以手動按位與運算. 以S_ISDIR為例, 在unistd.h中, 其定義:

#define S_ISDIR(mode) ((mode) & S_IFMT) == S_IFDIR)

示例: 創建2個文件, 分別是普通文件類型和目錄, 判斷並打印出文件類型
更詳細的示例 參見man 2 stat

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

#define FILE_NUM  2

void printFileType(char *path) {
    struct stat stat_buf;
    int ret = stat(path, &stat_buf);
    if (ret < 0) {
        perror("stat error");
        return;
    }

    if (S_ISREG(stat_buf.st_mode)) {
        printf("%s: general file\n", path);
    }
    else if(S_ISDIR(stat_buf.st_mode)) {
        printf("%s: direcotry\n", path);
    }
    else {
        printf("%s: other file type\n", path);
    }
}

int main() {
    char *filepaths[FILE_NUM] = {
        "./file", "./dir"
    };

    int ret = -1;
    for (int i = 0; i < FILE_NUM; ++i){
        if (access(filepaths[i], O_RDONLY) < 0) {
            ret = creat(filepaths[i], 0664);

            if (ret < 0) {
                perror("creat error");
                exit(1);
            }
        }
    }

    for (int i = 0; i < FILE_NUM; ++i) {
        printFileType(filepaths[i]);

    }
    return 0;
}

運行結果

$ touch file
$ mkdir dir
$ ./a.out 
./file: general file
./dir: direcotry


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM