ls命令
列出文件名和文件属性,默认找出当前目录中所有文件的文件名,按字典顺序排序后输出
-l 列出文件的详细信息
-a 列出隐藏文件
-lu 显示最后访问时间
-s 以块为单位的文件大小
-t 按时间排序
-F 显示文件类型
基础功能实现思路
目录:本质是文件列表,与utmp类似,都是数据序列,记录在dirent结构体
1.打开目录
2.循环获取dirent信息
3.关闭目录
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
void ls(char dirname[]) {
DIR *p_dir;
struct dirent *p_dirent;
if((p_dir = opendir(dirname)) == NULL)
fprintf(stderr, "open error: %s\n", dirname);
else {
while((p_dirent = readdir(p_dir)) != NULL) {
printf("%s\n", p_dirent -> d_name);
}
closedir(p_dir);
}
}
int main(int argc, char *argv[]) {
if(argc == 1) {
ls(".");
}
else {
while(--argc) {
ls(*++argv);
}
}
exit(0);
}
增加按字典顺序排序功能
获取到文件名之后,将文件名放到数组中,输出前对数组进行排序后输出
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
char *name[];
int index = 0;
void swap(int a, int b) {
char *temp;
temp = name[a];
name[a] = name[b];
name[b] = temp;
}
void mysort() {
for(int i = 0;i < index;i ++) {
int min_index = i;
for(int j = i;j < index;j ++) {
min_index = strcmp(name[min_index], name[j]) <= 0 ? min_index : j;
}
swap(min_index, j);
}
}
void print_name() {
mysort();
for(int i = 0;i < index;i ++)
puts(name[i]);
}
void ls(char dirname[]) {
DIR *p_dir;
struct dirent *p_dirent;
if((p_dir = opendir(dirname)) == NULL)
fprintf(stderr, "open error: %s\n", dirname);
else {
while((p_dirent = readdir(p_dir)) != NULL) {
name[index++] = p_dirent -> d_name;
}
closedir(p_dir);
print_name();
}
}
int main(int argc, char *argv[]) {
if(argc == 1) {
ls(".");
}
else {
while(--argc) {
ls(*++argv);
}
}
exit(0);
}
显示详细信息
ls -l命令 显示详细信息
<模式> 文件类型和文件访问权限
<链接数> 该文件被引用的次数
<文件所有者> 文件所有者的用户名
<组> 文件所有者在的组
<大小> 实际字节数
<最后修改时间>
<文件名>
获取文件属性信息
stat,在进程中创建stat结构体,调用stat函数,通知内核将文件属性放到进程的stat结构体中
man 2 stat查看结构体
char *filename = "ls.c";
struct stat file_info;
if(stat(filename, &file_info) != -1) {
}
模式信息格式化
stat结构体中的模式信息st_mode字段是int类型,但是ls -l命令中的模式是 -rw-rw-r--这种格式
void mode_to_str(int mode) {
char str[10] = {0};
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';
puts(str);
}
用户和组格式化
从stat中得到的用户和组信息都是int数值,但ls -l得到的是用户名和组名,使用getpwuid函数获取uid和用户名对应关系
char *uid_to_username(int uid) {
return getpwuid(uid) -> pw_name;
}
使用getgrgid函数获取gid和组名的对应关系
char *gid_to_groupname(int gid) {
return getgrgid(gid) -> gr_name;
}
时间参数格式化
void show_time(long timeval) {
struct tm *current_tm = localtime(&timeval);
printf("%d-%d-%d %d:%d:%d ", current_tm -> tm_year + 1900, current_tm -> tm_mon + 1, current_tm -> tm_mday, current_tm -> tm_hour, current_tm -> tm_min, current_tm -> tm_sec);
}
代码实现
// ls -l的代码实现
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
char *filename[256];
int array_index = 0;
void show_time(long timeval) {
struct tm *current_tm = localtime(&timeval);
printf("%4d-%4d-%4d %2d:%2d:%2d ", current_tm -> tm_year + 1900, current_tm -> tm_mon + 1, current_tm -> tm_mday, current_tm -> tm_hour, current_tm -> tm_min, current_tm -> tm_sec);
}
char *gid_to_groupname(int gid) {
return getgrgid(gid) -> gr_name;
}
char *uid_to_username(int uid) {
return getpwuid(uid) -> pw_name;
}
void mode_to_str(int mode) {
char str[10] = {0};
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';
printf("%s ", str);
}
void print_stat(char *filename) {
struct stat info;
if(stat(filename, &info) != -1) {
mode_to_str(info.st_mode);
printf("%ld ", info.st_nlink);
printf("%s ", uid_to_username(info.st_uid));
printf("%s ", gid_to_groupname(info.st_gid));
printf("%10ld ", info.st_size);
show_time(info.st_mtime);
puts(filename);
}
}
void swap(int a, int b) {
char *temp;
temp = filename[a];
filename[a] = filename[b];
filename[b] = temp;
}
void sort() {
for(int i = 0;i < array_index;i ++) {
int min_index = i;
for(int j = i;j < array_index;j ++) {
min_index = strcmp(filename[min_index], filename[j]) <= 0 ? min_index : j;
}
swap(min_index, i);
}
}
void print_filename() {
sort();
for(int i = 0;i < array_index;i ++)
print_stat(filename[i]);
}
void ls(char dirname[]) {
DIR *p_dir;
struct dirent *p_dirent;
if((p_dir = opendir(dirname)) == NULL) {
fprintf(stderr, "cannot open: %s\n", dirname);
}
else {
while((p_dirent = readdir(p_dir)) != NULL) {
filename[array_index++] = p_dirent -> d_name;
}
closedir(p_dir);
print_filename();
}
}
int main(int argc, char *argv[]) {
if(argc == 1)
ls(".");
else {
while(--argc) {
printf("%s:\n", *++argv);
ls(*argv);
}
}
exit(0);
}