C語言實現Linux之ls


ls命令用來顯示目標列表。

 

常用參數:

-l    :以長格式顯示目錄下的內容列表。輸出信息從左向右依次包括文件名,文件類型,權限模式,硬連接數,所有者、組、文件大小和文件的最后修改時間等;

-a   :顯示所有檔案及目錄;

-r    :以文件名反序排列並輸出目錄內容列表;

-t    :用文件和目錄的更改時間排序;

-R   :遞歸處理,將指定目錄下的所有文件及子目錄一並處理。

 

常用參數組合:

ls –rtl:反向按時間排序,查看一個目錄下最近修改的文件。

ls –full-time:在寫shell腳本的時候需要獲取文件被更新的時間,此命令可以獲取時間細微的變化。

 

獲取指定目錄下文件名:

/*
ls_name.c
*/
#include<stdio.h>
#include<sys/types.h>
#include<dirent.h>

void do_ls(char[]);

int main(int argc, char **argv)
{
    if (argc == 1)
    {
        do_ls(".");
    }
    else
    {
        while(--argc)
        {
            printf("%s:\n",*++argv);
            do_ls(*argv);
        }
    }

    return 0;
}


void do_ls(char dirname[])
{
    DIR* dir_ptr;
    struct dirent *direntp;

    if ((dir_ptr = opendir(dirname)) == NULL)
    {
        fprintf(stderr, "ls1: cannot open %s\n",dirname);
    }
    else
    {
        while((direntp = readdir(dir_ptr)) != NULL) 
        {
            //printf("direntp->d_name = %s\n",direntp->d_name);
            if(    strcmp(direntp->d_name, ".") != 0 &&
                strcmp(direntp->d_name, "..") != 0)
            printf("%s\n", direntp->d_name);
        }
        close(dir_ptr);
    }
}

 

運行結果:

 

獲取指定文件詳細信息:

/*
ls_fileinfo.c
*/
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>

void show_stat_info(char *filename, struct stat *buf)
{
    printf("mode\t\t:%o\n", buf->st_mode);
    printf("linkers\t\t:%d\n",(int)buf->st_nlink);
    printf("user\t\t:%d\n", buf->st_uid);
    printf("group_id\t:%d\n", buf->st_gid);
    printf("size\t\t:%d\n", (int)buf->st_size);
    printf("modtime\t\t:%d\n", (int)buf->st_mtime);
    printf("group_name\t:%s\n", filename);
}

int main(int argc, char **argv)
{
    struct stat info;

    if (argc > 1)
    {
        if (stat(argv[1], &info) != -1)
        {
            show_stat_info(argv[1], &info);
        }
        else
        {
            perror(argv[1]);
        }
    }

    return 0;
}

 

運行結果:

 

Linux下對於不同用戶的權限展示,分別是用戶、用戶組、所在組在stat結構體中的mode這個字段進行存儲。

mode字符是一個16位的二進制數,前4位用作文件類型,1代表具有某個屬性,0代表沒有。

接下來的三位分別為user-ID,set-group-ID和sticky位,最后9位是許可權限,分三組,每組3位。

這里使用掩碼的技術來划分,就跟ip中的子網掩碼一樣把2進制的1000000110110110划分為1,000,000,110,110,110,從而得到8進制的100664

對二進制進行位與操作,就是所謂的解碼。例如判斷目錄的代碼如下:

if ((info.st_mode & 0170000) == 0040000)
{
    printf(“this is a directory”);
}

用宏定義代替以上代碼:

#define S_ISFIFO(m)  (((m)&(0170000))==(0040000))
#define S_ISDIR(m)  (((m)&(0170000))==(0020000))
#define S_ISCHR(m)  (((m)&(0170000))==(0060000))
#define S_ISBLK(m)  (((m)&(0170000))==(0100000))
if(S_ISDIR(info.st_mode))
{
    printf("this is a directory");
}

 

獲取指定目錄下詳細文件信息

/*
ls_fin.c
*/
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<dirent.h>
#include<sys/stat.h>
#include<grp.h>
#include<pwd.h>

void do_ls(char []);
void dostat(char *);
void show_file_info(char *, struct stat *);
void mode_to_letters(int mode, char str[]);
char *uid_to_name(uid_t uid);
char *gid_to_name(gid_t gid);


int main(int argc, char **argv)
{
    if (argc == 1)
    {
        do_ls(".");
    }    
    else
    {
        while (--argc)
        {
            printf("%s:\n", *++argv);
            do_ls(*argv);
        }
    }

    return 0;
}

void do_ls(char dirname[])
{
    DIR *dir_ptr;
    struct dirent *direntp;

    if ((dir_ptr = opendir(dirname)) == NULL)
    {
        fprintf(stderr, "ls2: cannot open %s\n", dirname);
    }
    else
    {
        while((direntp = readdir(dir_ptr)) != NULL)
        {
            dostat(direntp->d_name);
        }
        closedir(dir_ptr);
    }
}

void dostat(char *filename)
{
    struct stat info;
    if (stat(filename, &info) == -1)
    {
        perror(filename);
    }
    else
    {
        show_file_info(filename, &info);
    }
}

void show_file_info(char *filename, struct stat *info_p)
{
    char *uid_to_name(), *ctime(), *gid_to_name();
    void mode_to_letters();
    char modestr[11];

    mode_to_letters(info_p->st_mode, modestr);

    printf("%s",modestr);
    printf("%4d ",(int)info_p->st_nlink);
    printf("%-8s ", uid_to_name(info_p->st_uid));
    printf("%-8s ", gid_to_name(info_p->st_gid));
    printf("%8ld ", (long)info_p->st_size);
    printf("%.12s ", 4 + ctime(&info_p->st_mtime));
    printf("%s\n", filename);
}

void mode_to_letters(int mode, char str[])
{
    strcpy(str, "-----------");

    if (S_ISDIR(mode))    str[0] = 'd';
    if (S_ISCHR(mode))    str[0] = 'c';
    if (S_ISBLK(mode))    str[0] = 'b';

    if (mode & S_IRUSR)    str[1] = 'r';
    if (mode & S_IWUSR) str[2] = 'w';
    if (mode & S_IXUSR)    str[3] = 'x';

    if (mode & S_IRGRP)    str[4] = 'r';
    if (mode & S_IWGRP)    str[5] = 'w';
    if (mode & S_IXGRP) str[6] = 'x';

    if (mode & S_IROTH) str[7] = 'r';
    if (mode & S_IWOTH)    str[8] = 'w';
    if (mode & S_IXOTH)    str[9] = 'x';
}

char *uid_to_name(uid_t uid)
{
    struct passwd * getpwuid(), *pw_ptr;
    static char numstr[10];

    if ((pw_ptr = getpwuid(uid)) == NULL)
    {
        sprintf(numstr, "%d", uid);
        return numstr;
    }
    else
    {
        return pw_ptr->pw_name;
    }
}

char *gid_to_name(gid_t gid)
{
    struct group *getgrgid(), *grp_ptr;
    static char numstr[10];

    if ((grp_ptr = getgrgid(gid)) == NULL)
    {
        sprintf(numstr, "%d", gid);
        return numstr;
    }
    else
    {
        return grp_ptr->gr_name;
    }
}

 

運行結果:


免責聲明!

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



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