C语言实现ls之myls改进
20191331 lyx
在之前的系统调用实践中已经实现myls-l命令
但该命令实现的并不完美,只能查看单一文件,且工程代码没有实现模块化
具体情况如下:
源代码链接:https://gitee.com/DKY2019/xxaqxt/blob/master/myls_l.c
现为实现完整的 ls-l
命令,做如下改进:
- 代码模块化
- 执行
ls -l ./
打印目录下所有文件
代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <utime.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
int print_type(mode_t st_mode){
char perms[11]={0};
switch (st_mode & S_IFMT){
case S_IFLNK:
perms[0]='l';
break;
case S_IFDIR:
perms[0]='d';
break;
case S_IFREG:
perms[0]='-';
break;
case S_IFBLK:
perms[0]='b';
break;
case S_IFCHR:
perms[0]='c';
break;
case S_IFSOCK:
perms[0]='s';
break;
case S_IFIFO:
perms[0]='p';
break;
default:
perms[0]='?';
break;
}
perms[1]=(st_mode & S_IRUSR) ? 'r':'-';
perms[2]=(st_mode & S_IWUSR) ? 'w':'-';
perms[3]=(st_mode & S_IXUSR) ? 'x':'-';
perms[4]=(st_mode & S_IRGRP) ? 'r':'-';
perms[5]=(st_mode & S_IWGRP) ? 'w':'-';
perms[6]=(st_mode & S_IXGRP) ? 'x':'-';
perms[7]=(st_mode & S_IROTH) ? 'r':'-';
perms[8]=(st_mode & S_IWOTH) ? 'w':'-';
perms[9]=(st_mode & S_IXOTH) ? 'x':'-';
printf("%s ", perms);
return 0;
}
int print_info(struct stat currentstat){
struct passwd *p_passwd;
struct group *p_group;
char *p_time;
int i;
p_time = ctime(¤tstat.st_mtime);
p_passwd = getpwuid(currentstat.st_uid);
p_group = getgrgid(currentstat.st_gid);
printf("%d ",(int)currentstat.st_nlink);
if(p_passwd != NULL)
printf("%s ",p_passwd->pw_name);
else
printf("%d ",(int)currentstat.st_uid);
if(p_group != NULL)
printf("%s ",p_group->gr_name);
else
printf("%d ",currentstat.st_gid);
printf("%7d ",(int)currentstat.st_size);
for(i=0; p_time[i] !=0 && p_time[i]!='
'; i++){
putchar(p_time[i]);
}
return 0;
}
int main(int argc, char* argv[]){
char buf[500];
DIR *currentdir = NULL;
struct dirent *currentdp = NULL;
struct stat currentstat;
if(argc != 2)
{
printf("%s need filename
",argv[0]);
exit(1);
}
memset(buf,0,500);
sprintf(buf,"%s",argv[1]);
currentdir = opendir(buf);
if(currentdir == NULL){
printf("open directory fail
");
return 0;
}
while((currentdp = readdir(currentdir)) != NULL)
{
if(currentdp->d_name[0] != '.')
{
sprintf(buf,"%s/%s",buf,currentdp->d_name);
if(lstat(buf,¤tstat) == -1){
printf("the dir:%s :",buf);
printf("get stat error
");
continue;
}
lstat(buf,¤tstat);
print_type(currentstat.st_mode);
print_info(currentstat);
printf(" ");
printf("%s
", currentdp->d_name);
memset(buf,0,500);
sprintf(buf,"%s",argv[1]);
}//if end
}//while end
closedir(currentdir);
return 0;
}
码云链接:https://gitee.com/DKY2019/xxaqxt/blob/master/myls相关练习/myls_l-2.c
执行效果:
完善myls
- 文件名读入数组,qsort()排序(为复习C语言,qsort手工完成,参考)
- 加入-a选项
- 计算列宽和行数
代码:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<dirent.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>
char *uid_to_name(uid_t uid)
{
struct passwd * getpwuid(),*pw_ptr;
static char numstr[10];
if((pw_ptr= getpwuid(uid))==NULL)
{
sprintf(numstr,"%d",uid);
return numstr;
}
else
return pw_ptr->pw_name;
}
char *gid_to_name(gid_t gid)
{
struct group *getgrgid(),*grp_ptr;
static char numstr[10];
if((grp_ptr=getgrgid(gid))==NULL)
{
sprintf(numstr,"%d",gid);
return numstr;
}
else
return grp_ptr->gr_name;
}
int find_mid(char(*data)[512], int l, int r)
{
int mid = (l + r) / 2;
if(strcmp(data[l], data[mid]) > 0)
{
int t = l;
l = mid;
mid = t;
}
if(strcmp(data[mid], data[r]) > 0)
{
int t = mid;
mid = r;
r = t;
}
return mid;
}
void swap(char *a, char *b)
{
char t[512];
strcpy(t, a);
strcpy(a, b);
strcpy(b, t);
}
void sort(char(*data)[512], int l, int r)
{
while(l < r)
{
int x = l, y = r;
int mid = find_mid(data, l, r);
do
{
while(strcmp(data[y], data[mid]) > 0)
y--;
while(strcmp(data[x], data[mid]) < 0)
x++;
if(x <= y)
{
swap(data[x++], data[y--]);
}
}
while(x <= y);
sort(data, x, r);
r = y;
}
}
int check_filename_color(int mode_bit)
{
int file_type = (mode_bit & 0170000);
if(file_type == 0040000) return 2;
if(mode_bit & 0000111) return 1;
return 0;
}
void printdir(char* dirname, int is_all)
{
char pathname[512];
char names[256][512];
int cnt_name = 0;
DIR* dir;
struct dirent* dp;
struct stat st;
if(!(dir = opendir(dirname)))
{
perror("opendir");
exit(1);
}
//weather filter "." ".."
while(dp = readdir(dir))
{
if(!is_all && dp -> d_name[0] == '.')
continue;
strcpy(names[cnt_name++], dp -> d_name);
}
sort(names, 0, cnt_name - 1);
//printf("[%s]
", names[0]);
for(int i = 0; i < cnt_name; i++)
{
sprintf(pathname, "%s/%s", dirname, names[i]);
if(stat(pathname, &st) == -1)
{
perror("stat");
exit(1);
}
int filename_color = check_filename_color(st.st_mode);
if(filename_color == 1)
{
printf("33[1;32m%s33[0m ", pathname + 2);
}
else if(filename_color == 2)
{
printf("33[1;34m%s33[0m ", pathname + 2);
}
else printf("%s ", pathname + 2);
}
closedir(dir);
printf("
");
}
int main(int argc, char* argv[])
{
int is_all = 0;
if(argc == 1)
{
printdir(".", is_all);
return 0;
}
if(argc > 1)
{
for(int i = 1; i < argc; i++)
{
if(argv[i][0] != '-') continue;
for(int j = 1; argv[i][j]; j++)
{
if(argv[i][j] == 'a') is_all = 1;
else
{
printf("invalid option, please check again!
");
exit(1);
}
}
}
}
int flag = 0;
for(int i = 1; i < argc; i++)
{
if(argv[i][0] == '-') continue;
flag = 1;
printdir(argv[i], is_all);
}
if(!flag) printdir(".", is_all);
return 0;
}
码云链接:https://gitee.com/DKY2019/xxaqxt/blob/master/myls相关练习/myls-2.c
执行效果:
参考资料
qsort使用方法 https://blog.csdn.net/C_time/article/details/88428100
C语言实现qsort https://blog.csdn.net/qq_43632625/article/details/93140277