首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

DIY Linux 命令系列:ls -l 參數完整實現(文件屬性、權限、用戶組、時間解析)

     編輯:關於C

功能目標

擴展基礎 ls,支援 -l 長格式輸出:類型、權限、鏈接數、擁有者、組、大小、修改時間、文件名。

核心 API:stat 結構體


struct stat {
    mode_t st_mode;   // 文件類型+權限位
    nlink_t st_nlink; // 硬鏈接數
    uid_t st_uid;     // 用戶ID
    gid_t st_gid;     // 組ID
    off_t st_size;    // 大小(字節)
    time_t st_mtime;  // 最後修改時間
};

關鍵解析邏輯

  1. 文件類型:S_ISDIR/REG/LNK/CHR/BLK/FIFO/SOCK 宏判斷 st_mode。
  2. 權限字符串:S_IRUSR/WUSR/IXUSR/GRP/OTH 位掩碼提取 rwx 三組。
  3. 用戶/組名:getpwuid(uid)->pw_name、getgrgid(gid)->gr_name。
  4. 時間格式:ctime(&st_mtime) 返回 "Wed Dec 31 18:00:00 2024\n",截取 [4..15] 去掉星期與年份。

完整 show_attr 實現


#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <string.h>

void show_attr(const char *name) {
    struct stat sb;
    if (stat(name, &sb) == -1) { perror("stat"); return; }

    char type = '?';
    if (S_ISLNK(sb.st_mode)) type = 'l';
    else if (S_ISREG(sb.st_mode)) type = '-';
    else if (S_ISDIR(sb.st_mode)) type = 'd';
    else if (S_ISCHR(sb.st_mode)) type = 'c';
    else if (S_ISBLK(sb.st_mode)) type = 'b';
    else if (S_ISFIFO(sb.st_mode)) type = 'p';
    else if (S_ISSOCK(sb.st_mode)) type = 's';

    char perm[10] = "---------";
    if (sb.st_mode & S_IRUSR) perm[0] = 'r';
    if (sb.st_mode & S_IWUSR) perm[1] = 'w';
    if (sb.st_mode & S_IXUSR) perm[2] = 'x';
    if (sb.st_mode & S_IRGRP) perm[3] = 'r';
    if (sb.st_mode & S_IWGRP) perm[4] = 'w';
    if (sb.st_mode & S_IXGRP) perm[5] = 'x';
    if (sb.st_mode & S_IROTH) perm[6] = 'r';
    if (sb.st_mode & S_IWOTH) perm[7] = 'w';
    if (sb.st_mode & S_IXOTH) perm[8] = 'x';

    struct passwd *pw = getpwuid(sb.st_uid);
    struct group  *gr = getgrgid(sb.st_gid);
    if (!pw || !gr) { perror("getpwuid/getgrgid"); return; }

    char timebuf[13];
    strncpy(timebuf, ctime(&sb.st_mtime) + 4, 12);
    timebuf[12] = '\0';

    printf("%c%s %2lu %-8s %-8s %6ld %s %s\n",
           type, perm, (unsigned long)sb.st_nlink,
           pw->pw_name, gr->gr_name,
           (long)sb.st_size, timebuf, name);
}

主程式調用


int main(int argc, char *argv[]) {
    int show_long = 0;
    if (argc > 1 && strcmp(argv[1], "-l") == 0) show_long = 1;

    DIR *dp = opendir(".");
    struct dirent *ep;
    while ((ep = readdir(dp))) {
        if (show_long) show_attr(ep->d_name);
        else printf("%s  ", ep->d_name);
    }
    if (!show_long) puts("");
    closedir(dp);
    return 0;
}

運行效果對比

$ ./myls -l
-rw-r--r-- 1 talk8 talk8   774 Dec 16 22:24 cat.c
-rw-r--r-- 1 talk8 talk8   596 Dec 13 09:59 cd.c
...
$ ls -l
-rw-r--r-- 1 talk8 talk8   774 Dec 16 22:24 cat.c
-rw-r--r-- 1 talk8 talk8   596 Dec 13 09:59 cd.c
...

輸出格式與系統 ls -l 高度一致。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved