在Linux中用C语言写一个自己的ls -l命令

在Linux中用C语言写一个自己的ls-l命令

在Linux中我们会经常使用ls -l 这条命令来查看文件信息,但是这个命令到底是怎么实现的呢?下面我就带大家用C语言来实现ls -l 这条命令,直接上代码吧:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>

// ls-l 功能函数,参数为一个文件名
void ls_l(char name[])
{
	// 定义一个stat类型的结构体
    struct stat my_stat;
    int ret = stat(name,&my_stat);
    if (ret  == -1){
        perror("stat");
        return ;
    }
    // 判断并打印文件类型 ,这里用到了很多函数调用,后面会为大家贴上这些函数的用法
    if (S_ISDIR(my_stat.st_mode))
        printf("d");
    else if (S_ISBLK(my_stat.st_mode))
        printf("b");
    else if (S_ISCHR(my_stat.st_mode))
        printf("c");
    else if (S_ISLNK(my_stat.st_mode))
        printf("l");
    else if (S_ISSOCK(my_stat.st_mode))
        printf("s");
    else if (S_ISREG(my_stat.st_mode))
        printf("-");
    else if (S_ISFIFO(my_stat.st_mode))
        printf("p");
    // 判断文件的权限信息
    printf("%c",(my_stat.st_mode) & (1<<8)?'r':'-');
    printf("%c",(my_stat.st_mode) & (1<<7)?'w':'-');
    printf("%c",(my_stat.st_mode) & (1<<6)?'x':'-');
    printf("%c",(my_stat.st_mode) & (1<<5)?'r':'-');
    printf("%c",(my_stat.st_mode) & (1<<4)?'w':'-');
    printf("%c",(my_stat.st_mode) & (1<<3)?'x':'-');
    printf("%c",(my_stat.st_mode) & (1<<2)?'r':'-');
    printf("%c",(my_stat.st_mode) & (1<<1)?'w':'-');
    printf("%c",(my_stat.st_mode) & (1<<0)?'x':'-');
    // 打印链接数
    printf(" %ld",my_stat.st_nlink);
    // 打印所属用户
    struct passwd *uid = getpwuid(my_stat.st_uid);
    printf(" %s",uid->pw_name);
    // 打印所属组
    struct group *gid = getgrgid(my_stat.st_gid);
    printf(" %s",gid->gr_name);
    // 打印文件大小
    printf(" %-8ld",my_stat.st_size);
    // 打印时间
    struct tm *t = localtime((time_t *)&my_stat.st_mtim);
    printf(" %d月   %d  %d:%d ",t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min);
    // 打印文件名
    printf("%-2s\n",name);

}
// 这里是使用命令行传参
int main(int argc, const char *argv[])
{
 //判断是否携带参数,如果没有携带参数,就默认为当前路径
 if (argc == 1){
        printf("请输入文件路径,或者文件名\n");
        return -1;
    }
    struct stat my_stat;
    int ret = stat(argv[1],&my_stat);
    // 判断输入的是否为目录
    if (S_ISDIR(my_stat.st_mode)){
    	// 如果为目录,我们将目录打开,把里面的内容(文件名)传给功能函数
        DIR * dir = opendir(argv[1]);
        if (NULL == dir){
            perror("opendir");
            return -1;
        }
        struct dirent *p = readdir(dir);
        if (NULL == p)
        {
            perror("readdir");
            return -1;
        }
        while (p!=NULL){
            ls_l(p->d_name);
            p = readdir(dir);
        }
        closedir(dir);
    }else  // 不是目录
        ls_l(argv[1]);

    return 0;
}

上述代码中用到了库函数和结构体,下面是一部分函数和结构体的具体内容:

  1. 【stat结构体的内容】
struct stat {
	dev_t     st_dev;     /* ID of device containing file */
	ino_t     st_ino;     /* inode number */
	mode_t    st_mode; 文件的权限、文件的类型   /* protection */
	nlink_t   st_nlink;   /* number of hard links */
	uid_t     st_uid;  所属用户ID   /* user ID of owner */ 
	gid_t     st_gid;  所属组ID   /* 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; /* blocksize for filesystem I/O */
	blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
	time_t    st_atime; 最后一次访问时间  /* time of last access */
	time_t    st_mtime; 最后一次修改时间  /* time of last modification */
	time_t    st_ctime; 最后一次文件文件属性修改时间  /* time of last status change */
};

2.【将uid 转换为 用户名】


#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
struct passwd {
   char   *pw_name;       /* username */
   char   *pw_passwd;     /* user password */
   uid_t   pw_uid;        /* user ID */
   gid_t   pw_gid;        /* group ID */
   char   *pw_gecos;      /* user information */
   char   *pw_dir;        /* home directory */
   char   *pw_shell;      /* shell program */
};
  1. 【将gid 转换为 组名】

#include <sys/types.h>
#include <grp.h>
struct group *getgrgid(gid_t gid);
struct group {
	char   *gr_name;       /* group name */
	char   *gr_passwd;     /* group password */
	gid_t   gr_gid;        /* group ID */
	char  **gr_mem;        /* group members */
};
  1. 【文件类型】
{
	常规文件:S_ISREG 	'-'
	目录:S_ISDIR 		'd'
	字符设备:S_ISCHR 	'c'
	块设备:S_ISBLK 	'b'
	管道:S_ISFIFO 		'p'
	套接字:S_ISSOCK 	's'
	符号链接:S_ISLNK 	'l'
}
  1. 【目录操作函数】


include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
/*****************************************
*功能: 打开一个目录文件
*参数: @name   	目录文件路径
*返回值:  成功  返回 目录流指针
*		  失败  返回 NULL   更新 errno
******************************************/


#include <dirent.h>
struct dirent *readdir(DIR *dirp);
/*****************************************
*功能: 读目录流指针
*参数: @dirp   	目录流指针
*返回值:  成功  返回 struct dirent 指针
*		  失败  返回 NULL 表示目录中的文件读完
******************************************/
struct dirent {
   ino_t          d_ino;       /* inode number */
   off_t          d_off;       /* not an offset; see NOTES */
   unsigned short d_reclen;    /* length of this record */
   unsigned char  d_type;      /* type of file; not supported
								  by all filesystem types */
   char           d_name[256]; /* filename */
};


#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
/*****************************************
*功能: 关闭目录流
*参数: @dirp   	目录流指针
*返回值:  成功  返回 0
*		  失败  返回 -1   更新 errno
******************************************/
上一篇:stat命令的学习与C语言实现


下一篇:MySQL数据库的下载和安装