/*
* 实现ls命令部分功能 -l -a -i -h
* 缺点:不能实现命令组合,如:‘ls -la’;
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <error.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#define BUFSIZE 1024
static int is_dir(const char *path); //判断是不是目录文件
static void my_stat(const char *path,const char option); //获取文件属性
void open_dir(const char *path, const char option) //打开文件
{
if(!is_dir(path)) //不是目录文件直接获取文件属性
{
my_stat(path,option);
return ;
}
DIR *dp = NULL;
dp = opendir(path); //获取目录流
struct dirent *entry = NULL;
if(dp == NULL)
{
perror("opendir()");
return;
}
while(1)
{
entry = readdir(dp);
if(entry == NULL)
{
if(error == NULL)
{
perror("readdir()");
closedir(dp);
return ;
}
break;
}
if(option == 'a') //如果是‘a’选项直接输出目录文件中包含的文件名
printf("%s\n", entry->d_name);
else
my_stat(entry->d_name, option); //其它选项将文件路径传给 my_stat 函数
}
closedir(dp);
return ;
}
int main(int argc, char *argv[])
{
char *p = "l::a::i::h::"; //定义选项
int opt;
while((opt = getopt(argc, argv, p)) != -1) //获取选项
{
switch(opt)
{
case 'l': //以长格式输出文件属性
if(optarg == NULL)
open_dir(".",'l');
else
open_dir(optarg,'l');
break;
case 'a': //输出所有文件名
if(optarg == NULL) //a后不加参数则读当前目录文件
open_dir(".",'a');
else //a后有参数读参数
open_dir(optarg,'a');
break;
case 'i':
if(optarg == NULL)
open_dir(".",'i');
else
open_dir(optarg,'i');
break;
case 'h':
if(optarg == NULL)
open_dir(".",'h');
else
open_dir(optarg,'h');
break;
case '?':
printf("不认识此选项%s\n",argv[optind-1]);
break;
case 1:
printf("非选项参数%s\n",argv[optind-1]);
break;
default:
break;
}
}
return 0;
}
static int is_dir(const char *path)
{
struct stat cur_stat;
if(stat(path, &cur_stat) < 0)
{
perror("lstat()");
return -1;
}
if(S_ISDIR(cur_stat.st_mode))
return 1;
return 0;
}
static void my_stat(const char *path,const char option)
{
if(option == 'a')
{
printf("%s\n",path);
return ;
}
struct stat file_att;
if(lstat(path, &file_att) == -1)
{
perror("lstat()");
return ;
}
/********************inode号**************************/
if(option == 'i')
{
printf("%ld ",file_att.st_ino);
}
/********************文件类型*************************/
switch(file_att.st_mode & S_IFMT)
{
case S_IFREG:
putchar('-');
break;
case S_IFDIR:
putchar('d');
break;
case S_IFCHR:
putchar('c');
break;
case S_IFBLK:
putchar('b');
break;
case S_IFIFO:
putchar('p');
break;
case S_IFSOCK:
putchar('s');
break;
case S_IFLNK:
putchar('l');
break;
default:
break;
}
/***************文件属性*********************/
//拥有者
if(file_att.st_mode & S_IRUSR)
putchar('r');
else
putchar('-');
if(file_att.st_mode & S_IWUSR)
putchar('w');
else
putchar('-');
if(file_att.st_mode & S_IXUSR)
{
if(file_att.st_mode & S_ISUID)
putchar('s');
else if(file_att.st_mode & S_ISGID)
putchar('g');
else if(file_att.st_mode & S_ISVTX)
putchar('t');
else
putchar('x');
}
else
putchar('-');
//所属组
if(file_att.st_mode & S_IRGRP)
putchar('r');
else
putchar('-');
if(file_att.st_mode & S_IWGRP)
putchar('w');
else
putchar('-');
if(file_att.st_mode & S_IXGRP)
putchar('x');
else
putchar('-');
//其他
if(file_att.st_mode & S_IROTH)
putchar('r');
else
putchar('-');
if(file_att.st_mode & S_IWOTH)
putchar('w');
else
putchar('-');
if(file_att.st_mode & S_IXOTH)
putchar('x');
else
putchar('-');
/**************硬链接个数***********************/
printf(" %ld ", file_att.st_nlink);
/**************文件拥有者***********************/
struct passwd *pwd = NULL;
pwd = getpwuid(file_att.st_uid);
printf("%s ",pwd->pw_name);
/**************文件所属组***********************/
struct group *grp = NULL;
grp = getgrgid(file_att.st_gid);
printf("%s ",grp->gr_name);
/**************文件总字节个数*******************/
if(option == 'l')
printf("%6ld ",file_att.st_size);
if(option == 'h')
printf("%6ldK ",file_att.st_blocks/2);
/**************最后修改时间*********************/
struct tm *tmp = NULL;
tmp = localtime(&file_att.st_mtim.tv_sec);
char buf[BUFSIZE] = {};
strftime(buf, BUFSIZE, "%m月 %d %H:%M", tmp);
printf("%s ",buf);
/**************文件名***************************/
printf("%s",path);
printf("\n");
return ;
}
运行结果:

网友评论