【一天一个命令的实现】ls命令

390 阅读3分钟

参考:《Unix-Linux编程实践》

命令功能

ls命令可以列出目录中所有文件的名字,以及这些文件的其他信息。

image.png ls还能显示其他信息,如果加上-l选项,ls会列出每个文件的详细信息

image.png

image.png

原理

文件树

Unix如何组织磁盘上的文件的呢?

磁盘上的文件和目录被组成一颗目录树,每个结点都是目录或者文件。

image.png Unix中每个文件都位于某个目录中,在逻辑上是没有驱动器或卷的,当然在物理上一个系统可以有多个驱动器或分区。

什么是目录

目录是一种特殊的文件,内容是该目录下的 文件和目录的名字。

也就是说,目录和上一章的utmp文件很类似,里面都包含很多记录,每个记录的格式由统一的标准定义,每条记录的内容代表一个文件或目录。

与普通文件不同的是,目录文件永远不会空,每个目录都至少包含两个特殊的项——“.”和“..”,其中“.”表示当前目录,后者表示上一级目录。

目录是文件的列表,更准确地说,是记录的序列,每条记录对应一个文件或子目录。

#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
//打开一个目录
//------------------
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
//返回目录中的当前项
//------------------
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
//0成功,-1失败

image.png

通过readdir来读取目录中的记录,readdir返回一个指向目录的当前记录的指针,该记录类型是struct dirent,这个结构定义在/usr/include/dirent.h

struct dirent{
    ino_t    d_ino;/* inode number 索引节点号 */
    off_t    d_off;/* offset to this dirent 在目录文件中的偏移 */
    unsigned short    d_reclen;/* length of this d_name 文件名长 */
    char     d_name[1]; //文件名
}

选项-l的详细信息

我们发现dirent结构中没有提供ls -l的详细信息,如文件大小,文件所有者等。 如果这些信息不是存储在目录中,那么它们会存储在什么地方呢?

用stat得到文件信息:

inode包含文件的元信息,可以用stat命令,查看某个文件的inode信息。

磁盘上的文件有很多属性,如文件大小,文件所有者的ID等,如果需要得到文件属性,进程可以定义个结构struct stat,然后调用stat,告诉内核把文件属性放在这个结构中。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *statbuf);

image.png

image.png

image.png

将用户/组 ID 转换为 用户名/组名

  1. 数据存在 /etc/passwd

  2. /etc/passwd并没有包含所有的用户

  3. 通过getpwuid来获得完整的用户列表

    可以通过库函数getpwuid来访问用户信息,如果用户信息保存在/etc/passwd中,那么getpwuid会查找其中的内容,如果用户信息在NIS中,getpwuid会从NIS中获取信息,所以用getpwuid使程序有很好的可移植性。