java实现ls命令_Linux下ls命令的简单模拟实现 | 学步园

这是我上操作系统这门课的习题,现在拿出来和大家分享一下。

欢迎大家和我的讨论与交流

/**

* Linux环境下ls命令的简单实现

* Copyright © 2011 Hang Studio. All rights reserved.

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

/*输出的组间隔*/

#define SPACE 2

/*获取无符号整型数十进制数的长度*/

unsigned get_unsigned_len(unsigned n){

unsigned len = 0;

do{

++len;

n /= 10;

}while(n);

return len;

}

/* “字符串”结构体 */

typedef struct{

char *str;/*实际内容*/

unsigned length;/*字符串长度*/

}String;

typedef struct{

unsigned length;/*集合中文件名的数量*/

unsigned i,j;/*i是行数,j是列数*/

String *filenames;

unsigned maxlen;/*文件名集合中最大的文件名长度*/

char **formats;/*格式化输出序列*/

}FormatInfo;

/*预读目录root,将格式化输出的信息保存在info里*/

void preread(char *root, FormatInfo *info){

DIR *dir;

unsigned i,j,count = 0;

struct dirent *ptr;

String filename;

/*g是根据目录下的目录项名的长度进行分组的辅助变量*/

unsigned *g = NULL;

unsigned width = 0;

unsigned group = 0;

unsigned max = 0;

unsigned row = 1;

unsigned pos = 0;

struct winsize t_size;

ioctl(STDIN_FILENO, TIOCGWINSZ, &t_size);/*获取终端的行数和列数*/

if(info == NULL){

printf("Error! /"info/" can not be NULL!/n");

return;

}

dir = opendir(root);

if(dir == NULL){

perror("Fail to open dir./n");

exit(1);

}

while(readdir(dir)) ++count;/*统计文件和目录的个数*/

rewinddir(dir);/*回卷读取目录的指针*/

info->filenames = (String *)malloc(sizeof(String) * count);

g = (unsigned *)malloc(sizeof(unsigned) * count);

i = 0;

/*获取文件或目录名和计算其长度*/

while((ptr = readdir(dir)) != NULL){

filename.str = ptr->d_name;/*文件或目录名*/

filename.length = strlen(ptr->d_name);

info->filenames[i++] = filename;

}

/*对目录项根据目录名或文件名从小到大进行排序*/

/*此处使用选择法排序*/

for(i=0;i

for(j=i;j

if(strcmp(info->filenames[i].str,

info->filenames[j].str) > 0){

filename = info->filenames[i];

info->filenames[i] = info->filenames[j];

info->filenames[j] = filename;

}

}

}

/*用试探的方法测试最后列表的组数*/

group = count;/*先假定分为count个列表*/

row = 1;/*每列的行数为1*/

do{

for(j=0,width=0;j

for(i=0,max=0;i

/*找出每一列中文件或目录名最长的那一个*/

pos = j*row + i;

if(pos >= count) break;

if(info->filenames[pos].length > max){

max = info->filenames[pos].length;

g[j] = max;/*把每个列表的最大宽度存放到g数组里*/

}

}

/*

* 将各组最长的文件或目录名的长度相加

* 把列表之间的间隔也算上

*/

width += (max + SPACE);

}

/* 假如其总宽度大于终端的宽度(列数)

* 则把分组列表的数量减少,继续试探。

*/

if(width >= t_size.ws_col){

--group;

/* 这里是根据总数量和列表数量

* 推算出每个列表的最大行数

*/

row = (count%group)?(count/group+1):(count/group);

}else{

/*否则,估算列表的数量结束*/

break;

}

}while(1);

/*接下来组织每个列表的格式化输出字符串*/

info->formats = (char **)malloc(sizeof(char *) * group);

info->maxlen = 0;

for(i=0;i

if(g[i] > info->maxlen)

info->maxlen = g[i];/*这里找出最大文件或目录名的长度,后面有用*/

g[i] += SPACE;/*把列表之间的间隔算上*/

j = get_unsigned_len(g[i]) + 4;

info->formats[i] = (char *)malloc(sizeof(char) * j);

sprintf(info->formats[i],"%%-%us",g[i]);/*这里就是组织格式化输出字符串的关键部分*/

info->formats[i][j] = '/0';

}

putchar('/n');

info->length = count;

info->i = row;/*列表行数*/

info->j = group;/*列表数量*/

free(g);

closedir(dir);

}

void my_ls(char *root){

FormatInfo fi;

int i,j,pos,len;

char *filepath = NULL;

struct stat buf;

preread(root,&fi);/*预读目录*/

len = strlen(root);

filepath = (char *)malloc(sizeof(char) *

(strlen(root)+fi.maxlen+1));

filepath[0] = '/0';

strcat(filepath,root);

if(filepath[len-1] != '/'){

filepath[len++] = '/';/*此处仅考虑在Linux系统下*/

}

for(i=0,pos=0;i

for(j=0;j

pos = j*fi.i + i;

if(pos < fi.length){

filepath[len] = '/0';

strcat(filepath, fi.filenames[pos].str);

stat(filepath, &buf);

if(S_ISDIR(buf.st_mode)){

/*假如是目录则将其着色为蓝色加粗字体*/

printf("/033[01;34m");

}else{

/*否则按默认的颜色显示*/

printf("/033[0m");

}

printf(fi.formats[j],fi.filenames[pos]);

}else if(i

break;

}else{

putchar('/n');

return;

}

}

putchar('/n');

}

printf("/33[0m");/*还原着色设置*/

free(filepath);

}

int main(int argc, char **argv){

if(argc < 1){

printf("Wrong usage/n");

exit(1);

}else if(argc == 1){

my_ls(".");

}else{

my_ls(argv[1]);

}

return 0;

}

保存其为“my_ls.c”,编译成为“dir”的可执行文件

[hang@localhost test]$ gcc my_ls.c -o dir

列出我当前目录下的内容,如果编译的时候指定其输出的可执行文件在当前目录下的话,记得在运行的时候最好在其前面加上“./”哦

[hang@localhost test]$ ./dir ~/

运行结果如下:

0_1307600439lHY2.gif

当然,这代码还存在的不足,例如将输出的文件名列表重定向到一个文件时,它会把着色的终端转义字符也一起输入到里面去...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值