红联Linux门户
Linux帮助

Linux下写自己的ls命令

发布时间:2014-11-02 15:56:23来源:linux网站作者:lr-ting

作者:曹忠明,华清远见嵌入式学院讲师。

ls命令是linux下最常用的命令之一,它的使用很简单,可是功能却很多,有很多的参数,这里我们就自己写一个ls命令,实现ls基本的功能。在这之前我们先介绍几个在实现ls过程中使用的函数。

stat/lstat函数

这两个函数功能基本相同,都是获得文件的属性,区别在于如果文件是符号链接stat返回的是符号链接指向文件的属性,而lstat返回的是符号链接本身的属性。

函数原型:

int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);

path为文件路径,buf为返回的状态,类型为struct stat,结构体内容为:

struct stat {
dev_tst_dev;/* ID of device containing file */
ino_t st_ino; /* inode number */
mode_tst_mode; /* protection */
nlink_t st_nlink;  /* number of hard links */
uid_t  st_uid;  /* user ID of owner */
gid_t st_gid;  /* 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 file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_tst_atime;/* time of last access */
time_tst_mtime;/* time of last modification */
time_tst_ctime;/* time of last status change */
};

这个结构体中成员st_mode用来表示文件的类型和文件的权限,它的定义如下:

S_IFMT0170000bit mask for the file type bit fields
S_IFSOCK0140000socket
S_IFLNK0120000symbolic link
S_IFREG 0100000regular file
S_IFBLK 0060000block device
S_IFDIR 0040000directory
S_IFCHR0020000  character device
S_IFIFO0010000FIFO
S_ISUID  0004000set UID bit
S_ISGID0002000 set-group-ID bit (see below)
S_ISVTX0001000sticky bit (see below)
S_IRWXU 00700 mask for file owner permissions
S_IRUSR  00400 owner has read permission
S_IWUSR  00200 owner has write permission
S_IXUSR 00100 owner has execute permission
 S_IRWXG  00070 mask for group permissions
S_IRGRP 00040group has read permission
S_IWGRP 00020  group has write permission
S_IXGRP00010  group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH  00004  others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH  00001 others have execute permission

我们可以通过下面宏来判断文件的类型

S_ISREG(m)    is it a regular file?
S_ISDIR(m)    directory?
S_ISCHR(m)    character device?
S_ISBLK(m)    block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m)    symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m)  socket? (Not in POSIX.1-1996.)

接着我们就实现ls的第一步:获得文件的属性

这个例子只能实现查看一个特定文件的属性,而ls实现的功能是如果是文件则显示文件属性,如果是目录则显示目录中各个文件的属性。
这些功能需要的函数为:

opendir/readdir函数用来获取目录项

原型:

DIR *opendir(const char *name);
struct dirent *readdir(DIR *dirp);
struct dirent描述目录中每一项的内容
struct dirent {
ino_td_ino; /* inode number */
off_td_off;/* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type;/* type of file; not supported by all file system types */
char d_name[256]; /* filename */
};

getopt用来实现命令选项功能:

原型:

int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;

readlink读取符号链接内容:

原型:

ssize_t readlink(const char *path, char *buf, size_t bufsiz);
path为符号链接路径
buf为符号链接内容
bufsize为要获得内容长度
文件按照属性显示颜色
033[mode;foreground;backgroundmhello\033[0m

mode为显示模式:
0、1、22、4、24、5、25、7、27,分别表示设定颜色、黑体、非黑体、下画线、非下画线、闪烁、非闪烁、翻转、非翻转。

foreground为前景颜色:
30 (黑色)、31 (红色)、32 (绿色)、33 (黄色)、34 (蓝色)、35 ( 紫红色)、36 (青色)和37 (白色)

background为背景颜色:
40 (黑色)、41 (红色)、42 (绿色)、43 (黄色)、44 (蓝色)、45 ( 紫红色)、46 (青色)和47 (白色)