做linux第四次实验,看错实验要求,花了一个下午自己模拟着实现一个ls命令。。。。

真是悲剧,看错了题目的意思,自己实现了一个 ls -l 命令。后来发现 C 可以直接调用系统命令。。。

记录一下自己如何模拟 ls 命令。。

ls -l 长格式的输出结果如下:

第一个字符代表的是该文件的类型:-(普通文件)、d(目录文件)、b(块设备文件)、c(字符设备文件)、p(管道文件)、l(符号链接文件)

之后的9个字符分为三组,分别是:文件所有者、同一用户组、其他用户。其中的三个字符分别的意思是:r(可读)、w(可写)、x(可执行)

之后可能出现的实心点不知道是什么意思。数字是对于普通文件似乎是硬链接的个数。

然后剩下的是所有者、所在用户组,文件大小,文件最新修改时间、文件名


首先,获取一个目录下的所有文件信息得用 opendir、readdir、closedir 这三个函数:

DIR * dp;
struct dirent *filename;
opendir(path);
while((filename=readdir(dp) != NULL)
{
    printf("filename %s\n", filename->d_name);
}
closedir(dp);
其中,dirent 的结构如下:
#include <dirent.h>
struct dirent
{
    long d_ino; /* inode number 索引节点号 */
    off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
    unsigned short d_reclen; /* length of this d_name 文件名长 */
    unsigned char d_type; /* the type of d_name 文件类型 */
    char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */}

而要获得文件其他更详细的信息,就得调用 stat 函数。

#include<unistd.h>
int stat(const char * file_name,struct stat *buf);

stat 函数的作用是将 file_name 指的文件状态复制到 buf 中。使用方法是:

struct stat buf;
while (filename=readdir(dp))
{
    stat(filename->d_name, &buf);
    do_somethine(buf);
}

struct stat 的定义如下:

#include<sys/stat.h>
struct stat
{
    dev_t st_dev; /* device 文件的设备编号 */
    ino_t st_ino; /* inode 文件的inode */
    mode_t st_mode; /* protection 文件的类型和存取的权限 */
    nlink_t st_nlink; /* number of hard links 连到该文件的硬连接数目,刚建立的文件值为1 */
    uid_t st_uid; /* user ID of owner 文件所有者的用户识别码 */
    gid_t st_gid; /* group ID of owner 文件所有者的组识别码 */
    dev_t st_rdev; /* device type 若此文件为装置设备文件,则为其设备编号 */
    off_t st_size; /* total size, in bytes 文件大小,以字节计算 */
    unsigned long st_blksize; /* blocksize for filesystem I/O 文件系统的 I/O 缓冲区大小 */
    unsigned long st_blocks; /* number of blocks allocated 占用文件区块的个数,每一区块大小为512个字节 */
    time_t st_atime; /* time of lastaccess 文件最近一次被存取或被执行的时间 */
    time_t st_mtime; /* time of last modification 文件最后一次被修改的时间 */
    time_t st_ctime; /* time of last change i-node最近一次被更改的时间 */
};
/* 其中有一下宏定义可以检查这些类型 */
if(S_ISLNK(st_mode)) printf("为符号连接\n");
if(S_ISREG(st_mode)) printf("为一般文件\n");
if(S_ISDIR(st_mode)) printf("为目录\n");
if(S_ISCHR(st_mode)) printf("为字符装置文件\n"); 

而文件的读写权限存储在 st_mode 变量二进制中的低9位。


而文件的所有者和所在用户组可以通过 stat 结构体中的 st_uid 和 st_gid 来获取。比如所有者的信息可以通过 getpwuid 函数获得:

// getpwuid 函数的定义
struct passwd * getpwuid(uid_t uid);

// 其中的 passwd 结构体定义如下
 struct passwd 
{ 
    char * pw_name; /* Username, POSIX.1 用户名 */ 
    char * pw_passwd; /* Password 用户加密后的密码 */ 
    __uid_t pw_uid; /* User ID, POSIX.1 用户的ID */ 
    __gid_t pw_gid; /* Group ID, POSIX.1 所在用户组ID */ 
    char * pw_gecos; /* Real Name or Comment field 所有者的详细用户名 */ 
    char * pw_dir; /* Home directory, POSIX.1 所有者主目录 */ 
    char * pw_shell; /* Shell Program, POSIX.1 所有者使用的shell */ 
};  

最后就是时间信息。时间信息我使用的是 stat 结构体中的 st_mtime ,可以通过 localtime 进行格式化:

// localtime 函数的定义
struct tm *localtime(const time_t * timep);

// tm 结构体的定义
struct tm
{
    int tm_sec; /* 目前秒数 */
    int tm_min; /* 目前分数 */
    int tm_hour; /* 午夜算起的时数,范围为0-23 */
    int tm_mday; /* 目前月份的日数,范围01-31 */
    int tm_mon; /* 目前月份 */
    int tm_year; /* 从1900 年算起至今的年数 */
    int tm_wday; /* 一星期的日数,从星期一算起 */
    int tm_yday; /* 从今年1月1日算起至今的天数 */
    int tm_isdst; /* 日光节约时间的旗标 */
};

通过这些,基本就可以模拟 ls 命令了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值