在学习linux系统编程的时候,实现了ls命令的简化版本号。

实现的功能例如以下

1. 每种文件类型有自己的颜色 (- 普通文件, d 文件夹文件, l 链接文件。 c 字符设备文件。 b 快设备文件, p 管道文件, s socket文件。共7种)

2. 支持的參数有 -hali (a: 显示隐藏文件。 i: 显示inode节点号,l: 以列表形式显示文件的具体信息。h: 人类可读的文件大小显示)

3. 对于符号链接,显示出其指向的文件。

4. 设备文件。显示主设备号和次设备号,不显示文件大小(设备文件没有大小属性,对于设备号,不同的 *nix 存储方式可能不同)

5. 文件依照字典序排序显示。

程序说明

1. 程序中大部分使用的都是linux系统调用和c标准库函数。仅仅有文件排序用到了c++ stl 的vector和sort算法(好吧,我又偷懒了!

2. lstat(): 获取文件的具体信息。inode, 权限, 连接数, uid, gid, size, time 等(对于符号链接文件。返回自身的信息,而不是目标文件的)

    opendir(), readdir(), closedir(): 读取文件夹信息。

    getpwuid(), getgrgid(): 通过uid, gid 获取用户和组的具体信息。

3. 对于不同文件类型的颜色。在Linux下能够使用env命令获取,也能够在程序中使用 extern char **environ 或 getenv() 获取。

程序编译执行(见下图)

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYV9yYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

程序源代码

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <dirent.h>
#include <grp.h>
#include <pwd.h> // c++
#include <vector>
#include <algorithm>
#include <string>
using namespace std; #define BUF_SIZE 1024 #define COLOR_R (char*)"\33[0m"
#define COLOR_D (char*)"\33[01m\33[34m"
#define COLOR_L (char*)"\33[01m\33[36m"
#define COLOR_P (char*)"\33[40m\33[33m"
#define COLOR_B (char*)"\33[40m\33[33m"
#define COLOR_C (char*)"\33[40m\33[33m"
#define COLOR_S (char*)"\33[02m\33[35m"
#define RESET_CLOLR (char*)"\33[0m" int get_option(const char *opt);
int show_ls();
int show_ls_one_path(const char *path);
int show_ls_file(const char *path, const char *name);
int show_ll_part(struct stat *p_stat, int bHuman);
void to_humen_size(char *buf, off_t size);
char get_file_type(mode_t st_mode);
void get_mode(char *buf, mode_t st_mode); // global var
enum EOPT
{
E_a, E_i, E_l, E_h, E_num
};
int g_opt[E_num] = {0}; // order: -ailh
char *g_scolor;
vector<string> gv_path; /* ls: ./a.out argv... */
int main(int argc, char const *argv[])
{
int i;
for (i = 1; i < argc; ++i)
{
if ('-' == argv[i][0])
{
if (-1 == get_option(argv[i]+1))
{
fprintf(stderr, "bad option!\n");
return 1;
}
}
else
{
gv_path.push_back(argv[i]);
}
} if (0 == gv_path.size())
{
gv_path.push_back(".");
} show_ls(); return 0;
} /* -ailh */
int get_option(const char *opt)
{
while (*opt != '\0')
{
switch (*opt)
{
case 'a':
g_opt[E_a] = 1;
break;
case 'i':
g_opt[E_i] = 1;
break;
case 'l':
g_opt[E_l] = 1;
break;
case 'h':
g_opt[E_h] = 1;
break;
default:
return -1;
}
opt++;
}
return 0;
} int show_ls()
{
for (vector<string>::iterator it = gv_path.begin();
it != gv_path.end(); ++it)
{
show_ls_one_path(it->c_str());
}
return 0;
} int show_ls_one_path(const char *path)
{
DIR *dir;
dir = opendir(path);
if (NULL == dir)
{
// not a dir
if (ENOTDIR == errno)
{
char *p = rindex((char *)path, '/');
if (NULL == p)
{
show_ls_file("./", path);
}
else
{
char sdir[BUF_SIZE] = {'\0'};
strncpy(sdir, path, p-path);
show_ls_file(sdir, p+1);
}
printf("\n");
return 0;
}
perror(path);
return -1;
} if (gv_path.size() > 1)
{
fprintf(stdout, "%s:\n", path);
} struct dirent *entry;
vector<string> v_name;
while (1)
{
entry = readdir(dir);
if (NULL == entry)
{
break;
}
// show conten depends on option(g_opt)
if (g_opt[E_a] != 1)
{
if ('.' == entry->d_name[0])
{
continue;
}
}
v_name.push_back(entry->d_name);
} // sort filename
sort(v_name.begin(), v_name.end());
for (vector<string>::iterator it = v_name.begin();
it != v_name.end(); ++it)
{
show_ls_file(path, it->c_str());
}
fprintf(stdout, "\n"); closedir(dir);
} int show_ls_file(const char *path, const char *name)
{
// stat
char full_path[BUF_SIZE];
int ret;
struct stat st_stat;
snprintf(full_path, BUF_SIZE, "%s/%s", path, name); ret = lstat(full_path, &st_stat);
if (-1 == ret)
{
perror(full_path);
return -1;
} if (1 == g_opt[E_i])
{
fprintf(stdout, "%7d ", (int)st_stat.st_ino);
} if (1 == g_opt[E_l])
{
show_ll_part(&st_stat, g_opt[E_h]);
}
else
{
get_file_type(st_stat.st_mode);//get file color actually
} // show filename with color
fprintf(stdout, "%s", g_scolor);
fprintf(stdout, "%s ", name);
fprintf(stdout, RESET_CLOLR);
if (1 == g_opt[E_l] && 'l' == get_file_type(st_stat.st_mode))
{
// -> real file
char real_file[BUF_SIZE];
int path_size = readlink(full_path, real_file, BUF_SIZE);
real_file[path_size] = '\0';
fprintf(stdout, "-> %s", real_file);
} if (1 == g_opt[E_l])
{
fprintf(stdout, "\n");
}
return 0;
} /* show ll: mode, link num, user, group, size, time */
int show_ll_part(struct stat *p_stat, int bHuman)
{
// mode
char buf[BUF_SIZE];
get_mode(buf, p_stat->st_mode);
char file_type = buf[0];
fprintf(stdout, "%s", buf); // link num
fprintf(stdout, " %d", p_stat->st_nlink); // uid gid
// get_id_name(buf, p_stat->st_uid, "/etc/passwd");
// fprintf(stdout, " %s", buf);
// get_id_name(buf, p_stat->st_gid, "/etc/group");
// fprintf(stdout, " %s", buf);
struct passwd * st_user = getpwuid(p_stat->st_uid);
fprintf(stdout, " %s", st_user->pw_name);
struct group * st_group = getgrgid(p_stat->st_gid);
fprintf(stdout, " %s", st_group->gr_name); // show dev id
if ('c' == file_type || 'b' == file_type/* || 'p' == file_type*/)
{
// dev_id
int major = 0xFF00 & p_stat->st_rdev;
major >>= 8;
int sub = 0x00FF & p_stat->st_rdev;
fprintf(stdout, "\t%4d,%4d", major, sub);
}
else // show file size
{
// -h bHuman size
off_t size = p_stat->st_size;
if (bHuman)
{
char buf[BUF_SIZE];
to_humen_size(buf, size);
fprintf(stdout, " %s", buf);
}
else
{
fprintf(stdout, " %9ld", size);
}
} // time
char stime[BUF_SIZE] = {'\0'};
snprintf(stime, 13, "%s", 4+ctime(&p_stat->st_ctime));
fprintf(stdout, " %s ", stime); return 0;
} // -h option
void to_humen_size(char *buf, off_t size)
{
double tmp = size;
if (size >= 1024*1024*1024)
{
tmp /= 1024*1024*1024;
snprintf(buf, BUF_SIZE, "%5.1fG", tmp);
}
else if (size >= 1024*1024)
{
tmp /= 1024*1024;
snprintf(buf, BUF_SIZE, "%5.1fM", tmp);
}
else if (size >= 1024)
{
tmp /= 1024;
snprintf(buf, BUF_SIZE, "%5.1fK", tmp);
}
else
{
snprintf(buf, BUF_SIZE, "%6ld", size);
}
} char get_file_type(mode_t st_mode)
{
if (S_ISREG(st_mode))
{
g_scolor = COLOR_R;
return '-';
}
if (S_ISDIR(st_mode))
{
g_scolor = COLOR_D;
return 'd';
}
if (S_ISCHR(st_mode))
{
g_scolor = COLOR_C;
return 'c';
}
if (S_ISBLK(st_mode))
{
g_scolor = COLOR_B;
return 'b';
}
if (S_ISFIFO(st_mode))
{
g_scolor = COLOR_P;
return 'p';
}
if (S_ISLNK(st_mode))
{
g_scolor = COLOR_L;
return 'l';
}
if (S_ISSOCK(st_mode))
{
g_scolor = COLOR_S;
return 's';
}
g_scolor = COLOR_R;
return '-';
} // -rwx---...
void get_mode(char *buf, mode_t st_mode)
{
buf[0] = get_file_type(st_mode); int i;
mode_t bit;
for (i = 3; i > 0; --i)
{
bit = st_mode & 0x01;
buf[i*3] = (1 == bit ? 'x' : '-');
st_mode >>= 1; bit = st_mode & 0x01;
buf[i*3-1] = (1 == bit ? 'w' : '-');
st_mode >>= 1; bit = st_mode & 0x01;
buf[i*3-2] = (1 == bit ? 'r' : '-');
st_mode >>= 1;
}
buf[10] = '\0';
}

本文地址http://blog.csdn.net/a_ran/article/details/25178417

Linux ls 命令实现(简化版)的更多相关文章

  1. linux ls命令教程,ls命令怎么用,全部招数都教你

    linux ls命令的用法大全 学习linux这么久了,最常用的命令莫属 ls命令了,今天就总结下ls命令的用法与经验技巧.   ls命令按文件大小查看文件   a.降序:ls -lsh moudae ...

  2. Linux ls命令详解

    ls 命令可以说是Linux下最常用的命令之一. -a 列出目录下的所有文件,包括以 . 开头的隐含文件.(后有详解)-b 把文件名中不可输出的字符用反斜杠加字符编号(就象在c语言里一样)的形式列出. ...

  3. linux ls 命令

    ls 命令是 Linux 下最常用的命令之一,用来查询目录下的内容(list directory contents).本文将介绍其基本的用法和一些典型的用例.笔者使用的测试环境为 ubuntu 16. ...

  4. Linux ls命令

    ls:即列表List的意思,用来列出目录下的文件用来列出给定目录下的文件,参数为空默认列出当前目录下的文件. 用法是:ls [选项] [目录] 常用的选项有 -a, –all 列出目录下的所有文件,包 ...

  5. linux ls命令按时间显示文件

      本文介绍下,使用ls命令显示文件,并按时间排序的方法,供大家学习参考. 在linux系统中,使用ls命令按时间排序文件,其实很简单,如下: #ls -tr 即可按时间排序当前目录下的文件. 附,l ...

  6. Linux ls命令参数详解

    -a -- 全部(all).列举目录中的全部文件,包括隐藏文件(.filename).位于这个列表的起首处的 .. 和 . 依次是指父目录和你的当前目录.      -l -- 长(long).列举目 ...

  7. Linux ls命令参数详解 <转>

    下面是一个与 ls 一起使用的一些常用选项的简短列表.请记住,你可以通过阅读 ls 的说明书页(man ls)来获得选项的完整列表. -a – 全部(all).列举目录中的全部文件,包括隐藏文件(.f ...

  8. 你应该了解的 7个Linux ls 命令技巧

    在前面我们系列报道的两篇文章中,我们已经涵盖了关于‘ls’命令的绝大多数内容.本文时‘ls命令’系列的最后一部分.如果你还没有读过该系列的其它两篇文章,你可以访问下面的链接. 15 个‘ls’命令的面 ...

  9. Linux ls命令详解-乾颐堂CCIE

      ls命令用法举例: 例一:列出/home文件夹下的所有文件和目录的详细资料: 1 ls -l -R /home 命令参数之前要有一短横线“-”, 上面的命令也可以这样写: 1 ls -lR /ho ...

随机推荐

  1. 记一次面经pm

    记一次面经 介绍下你自己的这个项目. 浅谈一下数据结构.    参考网站    在我的记忆中,数据结构包括链表.线性表.栈与队列.数组.一些排序,比如冒泡排序.快速排序.希尔排序.堆排序等,还有一些树 ...

  2. 3. Python基础语法

    注释 我们在文言文中经常会看到注释,注释可以帮助读者对文章的理解.代码中的注释也是一样,优秀的代码注释可以帮助读者对代码的理解.当然在代码编写过程中,注释的使用不一定只是描述一段代码,也可能的是对代码 ...

  3. 软件测试工程师如何提高提BUG逼格

    某个周四早上,沏好一杯茶,刚要坐到座位上,就听开发说,你们测试怎么提的Bug,给个截图能说明啥?截图上面显示的奔溃,如果是必现还好,如果不是必现,那么我们怎么去定位?至少给个日志吧?当时我的内心活动是 ...

  4. leetcode 596 BUG笔记

    There is a table courses with columns: student and class Please list out all classes which have more ...

  5. img路径错误时,用户友好图片

    img 标签的属性里面添加 onerror="this.src='error友好图片'" 就可以了!

  6. Codeforces 1169A Circle Metro

    题目链接:codeforces.com/contest/1169/problem/A 题意:有俩个地铁,一个从 1 → 2 → …→ n → 1→ 2 →…, 一个 从 n → n-1 →…→ 1 → ...

  7. 注册页面-使用form模块搭建

    基于Django的form模块,快速的搭建注册页面,每个限制条件,都放在form模块里面,不单独对每一项编写标签,使用模版的 for 循环来渲染. 首先设置form模块 在blogs模块下创建一个bl ...

  8. 关于js 重载

    拜读js忍者修炼一书 读到关于js函数重载内容这个模块 主要是介绍通过js的访问argument这个参数来实现js函数的重载 通过在函数内部进行判断js argument参数的长度 代码如下所示 va ...

  9. 30个优秀的CSS技术和实例 By 彬Go 2008-12-04

    在这里可发现很多与众不同的技术,比如:图片集.阴影效果.可扩展按钮.菜单等…这些实例都是使用纯CSS和HTML实现的.单击每个实例的标题可以被转向到该技术实例的相关教程或说明页面(英文),单击每个实例 ...

  10. 伪类checked

    困惑了好久的复选框自定义样式终于有了谜底,原来就是一个 :checked 伪类 他的意思就是 匹配任意被勾选/选中的radio(单选按钮),chexked(复选框),或者option(select项) ...