Linuxls命令实现(简化版)

本文发布时间: 2019-Mar-22
在学习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. stat(): 获取文件的详细信息,inode, 权限, 连接数, uid, gid, size, time 等 opendir(), readdir(), closedir(): 读取目录信息程序编译运行(见下图)程序源码:#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 varenum EOPT{E_a, E_i, E_l, E_h, E_num};int g_opt[E_num] = {0}; // order: -ailhchar *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 dirif (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 filenamesort(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){// statchar 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 colorfprintf(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 filechar 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){// modechar buf[BUF_SIZE];get_mode(buf, p_stat->st_mode);char file_type = buf[0];fprintf(stdout, "%s", buf);// link numfprintf(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 idif ('c' == file_type || 'b' == file_type/* || 'p' == file_type*/){// dev_idint 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 sizeoff_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);}}// timechar stime[BUF_SIZE] = {'\0'};snprintf(stime, 13, "%s", 4+ctime(&p_stat->st_ctime));fprintf(stdout, " %s ", stime);return 0;}// -h optionvoid 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';}


(以上内容不代表本站观点。)
---------------------------------
本网站以及域名有仲裁协议。
本網站以及域名有仲裁協議。

2024-Mar-04 02:10pm
栏目列表