• 姓名：李瑶
• 学号：201821121002
• 班级：计算1811

# 1. 编写程序

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<dirent.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>

#define PARAMETER_NONE 0
#define PARAMETER_A 1
#define PARAMETER_L 2
#define MAXROWLEN 80
int g_leave_len = MAXROWLEN;
int g_maxlen;
void error(const char *err_string, int line);
void Demonstrate_attribute(struct stat buf, char * name);
void Demonstrate_single(char * name);
void Demonstrate(int flag, char * pathname); /
void Demonstrate_dir(int flag_parameter, char * path);

int main(int argc, char ** argv){
int i, j, k, num;
char path[PATH_MAX+1]; //文件路径名
char parameter[32]; // 保存命令行参数
int flag_parameter = PARAMETER_NONE; // 用来标志参数种类
struct stat buf;
j = 0,
num = 0;
for (i = 1 ; i < argc; i++){
if (argv[i][0] == '-'){
for(k = 1; k < strlen(argv[i]); k++){
parameter[j] = argv[i][k]; // 获取-后面的参数保存到数组parameter中
j++;
}
num++; // 保存"－"的个数
}
}
for(i = 0; i < j; i++){
if (parameter[i] == 'a'){
flag_parameter = PARAMETER_A;
continue;
}
else if (parameter[i] == 'l'){
flag_parameter = PARAMETER_L;
continue;
}
else{
printf("my_ls: invalid option -%c\n", parameter[i]);
exit(1);
}
}
parameter[j] = '\0';
if ((num + 1) == argc){
strcpy(path, "./");// "./"当前目录
path[2] = '\0';
Demonstrate_dir(flag_parameter, path);
return 0;
}
i=1;
do {
if (argv[i][0] == '-'){
i++;
continue;
}
else{
strcpy(path, argv[i]);
if ( stat(path, &buf) == -1 ){
error("stat", __LINE__);
}
if ( S_ISDIR(buf.st_mode) ) // argv[i]是一个目录{
if ( path[ strlen(argv[i])-1 ] != '/'){
path[ strlen(argv[i]) ] = '/';
path[ strlen(argv[i])+1 ] = '\0';
}
else{
path[ strlen(argv[i]) ] = '\0';
}
Demonstrate_dir(flag_parameter,path);
i++;
}
else{
Demonstrate(flag_parameter, path);
i++;
}
}
} while (i < argc);
return 0;
}
void error(const char *err_string, int line){
fprintf(stderr, "line:%d ", line);
perror(err_string);
exit(1);
}
void Demonstrate_attribute(struct stat buf, char * name){
char buf_time[32]; //存放时间
struct passwd *psd; //从该结构体中获取文件所有者的用户名
struct group *grp; //从该结构体中获取文件所有者所属组的组名
if (S_ISLNK(buf.st_mode)){
printf("l");
}
else if (S_ISREG(buf.st_mode)){
printf("-");
}
else if (S_ISDIR(buf.st_mode)){
printf("d");
}
else if (S_ISCHR(buf.st_mode)){
printf("c");
}
else if (S_ISBLK(buf.st_mode)){
printf("b");
}
else if (S_ISFIFO(buf.st_mode)){
printf("f");
}
else if (S_ISSOCK(buf.st_mode)){
printf("s");
}
if (buf.st_mode & S_IRUSR){
printf("r");
}
else{
printf("-");
}
if (buf.st_mode & S_IWUSR){
printf("w");
}
else{
printf("-");
}
if (buf.st_mode & S_IXUSR){
printf("x");
}
else{
printf("-");
}
if (buf.st_mode & S_IRGRP){
printf("r");
}
else{
printf("-");
}
if (buf.st_mode & S_IWGRP)
{
printf("w");
}
else{
printf("-");
}
if (buf.st_mode & S_IXGRP){
printf("x");
}
else{
printf("-");
}
if (buf.st_mode & S_IROTH){
printf("r");
}
else{
printf("-");
}
if (buf.st_mode & S_IWOTH){
printf("w");
}
else
{
printf("-");
}
if (buf.st_mode & S_IXOTH){
printf("x");
}
else{
printf("-");
}
printf(" ");
psd = getpwuid(buf.st_uid);
grp = getgrgid(buf.st_gid);
printf("%-9s", psd->pw_name); //打印文件拥有者
printf("%-8s", grp->gr_name); //打印文件所属用户组
printf("%6d",(int)buf.st_size); // 打印文件的大小
strcpy(buf_time, ctime(&buf.st_mtime));
buf_time[strlen(buf_time) - 1] = '\0'; // 去掉换行符
printf(" %s", buf_time); // 打印文件的时间信息
}
void Demonstrate_single(char *name){
int i, len;
if (g_leave_len < g_maxlen){
printf("\n");
g_leave_len = MAXROWLEN;
}
len = strlen(name);
len = g_maxlen - len;
printf("%-s", name);
for (i = 0; i < len; i++){
printf(" ");
}
printf(" ");
g_leave_len -= (g_maxlen + 2);
}
void Demonstrate(int flag, char * pathname){
int i, j;
struct stat buf;
char name[NAME_MAX + 1];
for (i = 0, j = 0; i < strlen(pathname); i++){
if (pathname[i] == '/'){
j = 0;
continue;
}
name[j++] = pathname[i];
}
name[j] = '\0';
if ( lstat(pathname, &buf) == -1 ){
error("stat", __LINE__);
}
switch (flag){
case PARAMETER_NONE: // 没有-l和-a选项
if (name[0] != '.'){
Demonstrate_single(name);
}
break;
case PARAMETER_A: // -a:显示包括隐藏文件在内的所有文件
Demonstrate_single(name);
break;
case PARAMETER_L: // -l:每个文件单独占一行，显示文件的详细属性信息
if (name[0] != '.'){
Demonstrate_attribute(buf, name);
printf(" %-s\n", name);
}
break;
case PARAMETER_A + PARAMETER_L: // 同时有-a和-l选项的情况
Demonstrate_attribute(buf, name);
printf(" %-s\n", name);
break;
default:
break;
}
}
void Demonstrate_dir(int flag_parameter, char *path){
DIR *dir;
struct dirent *ptr;
int count = 0;
char filenames[256][PATH_MAX + 1],temp[PATH_MAX + 1];// 获取该目录下文件总数和最长的文件名
dir = opendir(path);
if (dir == NULL){
error("opendir", __LINE__);
}
while ((ptr = readdir(dir)) != NULL){
if (g_maxlen < strlen(ptr->d_name))
g_maxlen = strlen(ptr->d_name);
count++;
}
closedir(dir);
if(count > 256)
error("too many files under this dir",__LINE__);
int i, j, len = strlen(path);// 获取该目录下所有的文件名
dir = opendir(path);
for(i = 0; i < count; i++){
if( ptr == NULL){
}
strncpy(filenames[i],path,len); //filenames存放目录下的所有文件名
filenames[i][len] = '\0';
strcat(filenames[i],ptr->d_name);
filenames[i][len + strlen(ptr->d_name)] = '\0';
}
for(i = 0; i < count-1; i++)
for(j = 0; j < count - 1 - i; j++)
{
if( strcmp(filenames[j],filenames[j + 1]) > 0 )
{
strcpy(temp,filenames[j + 1]);
temp[strlen(filenames[j + 1])] = '\0';
strcpy(filenames[j + 1],filenames[j]);
filenames[j + 1][strlen(filenames[j])] = '\0';
strcpy(filenames[j], temp);
filenames[j][strlen(temp)] = '\0';
}
}
for(i = 0; i < count; i++)
Demonstrate(flag_parameter, filenames[i]);
closedir(dir);
if( (flag_parameter & PARAMETER_L) == 0)
printf("\n");
}

# 2. 分析运行结果

drwxr-xr-x代表文件的类型及权限

### ls 命令

-a 显示所有文件及目录 (ls内定将文件名或目录名称开头为"."的视为隐藏档，不会列出)
-l 除文件名称外，亦将文件型态、权限、拥有者、文件大小等资讯详细列出
-r 将文件以相反次序显示(原定依英文字母次序)
-t 将文件依建立时间之先后次序列出
-A 同 -a ，但不列出 "." (目前目录) 及 ".." (父目录)
-F 在列出的文件名称后加一符号；例如可执行档则加 "*", 目录则加 "/"
-R 若目录下有文件，则以下之文件亦皆依序列出

posted on 2020-04-30 18:54  霓袅  阅读(148)  评论(0编辑  收藏  举报