在学习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. int在64位操作系统中占多少位?

    仍然是32位. 曾经是这样的:16位操作系统中,int 占16位:在32位操作系统中,int 占32位.但是现在人们已经习惯了 int 占32位,因此在64位操作系统中,int 仍为32位.64位整型 ...

  2. 在Windows的控制台和Linux的终端中显示加载进度

    Windows中 #include <stdio.h> #include <windows.h> int main() { ;//任务完成总量 int i; ; i < ...

  3. Spellchecker inspection helps locate typos and misspelling in your code, comments and literals, and fix them in one click

    Pycharm设置 Pycharm总是很多的拼写检查波拉线 Spellchecker inspection helps locate typos and misspelling in your cod ...

  4. IDM自定义报错页面

    由于用户两次重复单点登录会跳转至原生态ORACLE的错误页面页面.请提供配置方法.原因:是由于重复登录导致的.解决方案:Oracle官方给出了具体的解决方案,具体如下:I.创建战争档案a.创建目录&q ...

  5. Java中的注解是如何工作的?

    自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Override,@Deprecated这样的注解.这篇文章中,我将向大家讲述 ...

  6. 并发编程之Android中AsyncTask使用详解(四)

    更多Android高级架构进阶视频免费学习请点击:[https://space.bilibili.com/474380680] 在Android中我们可以通过Thread+Handler实现多线程通信 ...

  7. centos 时区设置初认识

    由于一些需要,我租用了一个海外服务器,并开始了我的centos之旅. 由于之前一直用虚拟机,而且在国内,所以不需要考虑时区的问题,但是现在,这个服务器是在海外的,所以就必须考虑时区的问题了.更何况我的 ...

  8. vs2013 命名空间“Microsoft.Office”中不存在类型或命名空间名称“Interop”。是否缺少程序集引用?

    参考博文: 解决办法:添加引用/com/Microsoft Office 11.0 Object Library 然后在程序中 C#代码 using Microsoft.Office.Interop. ...

  9. LINUX内核及应用程序移植工作

    1. 添加工作用户 [root@localhost ~]#useradd -G root -g root -d/home/arm arm 2. 建立工作目录 [arm@localhost arm]$m ...

  10. ARM TK1 安装ROS- indigo

    之前安装不成功是因为校园网无法访问源的问题. Ubuntu ARM install of ROS Indigo There are currently builds of ROS for Ubuntu ...