一个简单的“ls -al”实现(其实网上已经有很多了)
2011-01-06 15:44
585 查看
/**
* Copyleft (C) 2010 Late Lee
* This program is tested on LINUX PLATFORM, WITH GCC 4.x.
* The program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY. Please feel free to
* use the program, and I feel free to ignore the related
* issues. Any questions or suggestions, or bugs, please
* contact me at
* $ echo -n "aHR0cDovL3d3dy5sYXRlbGVlLm9yZwo=" | base64 -d
* or e-mail to
* $ echo -n "bGF0ZWxlZUAxNjMuY29tCg==" | base64 -d
* if you want to do this.
*
* @file: myls.c
* @author: Late Lee
* @date: Thu Jan 6 2011
* @brief: An "ugly" implementation of "ls -la".
*
* @test: gcc -Wall myls.c -o myls
* "./myls" will display the current directory, or you can specify
* the directory(or the file), such as "./myls /", etc.
* @note: I do not know how to print the "real" name of a symbolic link file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h> /* stat */
#include <grp.h> /* getgrgid() */
#include <pwd.h> /* passwd, getpwuid(), etc */
#include <time.h>
#include <string.h>
#include <dirent.h> /* opendir(), etc */
static int get_file_name(char *file, const char *path)
{
if (file == NULL || path == NULL)
{
printf("Error: do you forget malloc??/n");
return -1;
}
int len = strlen(path);
int pos = len - 1;
while (pos>=0 && path[pos]!='/' )
pos--;
strcpy(file, path + pos + 1);
return 0;
}
static int display_file_name(const char *path)
{
int len = 0;
char *file = NULL;
len = strlen(path);
file = (char *)malloc(len+1);
get_file_name(file, path);
printf("%s ", file);
free(file);
return 0;
}
static int display_attr(const char *file)
{
struct stat buf;
int ret;
char *m; /* OK here */
ret = lstat(file, &buf);
if (ret == -1)
{
perror("lstat error");
//return -1;
exit(0);
}
/**
* file mode
* st_mode sample(in oct):
* 0 12 0 7 4 4
* l rwx rw- rw-
* oct type ?? owner group others
* see man page for details($man lstat)
*/
if (S_ISREG(buf.st_mode))
m = "-";
else if (S_ISDIR(buf.st_mode))
m = "d";
else if (S_ISCHR(buf.st_mode))
m = "c";
else if (S_ISBLK(buf.st_mode))
m = "b";
else if (S_ISFIFO(buf.st_mode))
m = "f";
else if (S_ISLNK(buf.st_mode))
m = "l";
else if (S_ISSOCK(buf.st_mode))
m = "s";
else /* just kidding */
m = "-";
printf("%s", m);
/*file permission*/
int n;
int temp;
int tmp;
for (n=8; n>=0; n--)
{
/**
* temp:
* dec 256 128 64 32 16 8 4 2 1
* oct 0400 0200 0100 0040 0020 0010 0004 0002 0001
*/
temp = 1<<n;
tmp = buf.st_mode & temp;
if (tmp)
// if (buf.st_mode & (1<<n))
{
switch (n%3)
{
case 2: printf("r"); break;
case 1: printf("w"); break;
case 0: printf("x"); break;
}
}
else
printf("-");
}
printf(" ");
/* number of hard link */
printf("%3d ", buf.st_nlink);
/* user name */
struct passwd *pw = getpwuid(buf.st_uid);
printf("%8s ", pw->pw_name);
/* group name */
struct group *grp = getgrgid(buf.st_gid);
printf("%8s ", grp->gr_name);
/* file size */
printf("%5d ", (int)buf.st_size);
/* last modify time */
struct tm *t;
t = localtime(&(buf.st_mtime));
printf("%4d-%02d-%02d %02d:%02d ", t->tm_year+1900, t->tm_mon+1,
t->tm_mday, t->tm_hour, t->tm_min);
/* file name... */
printf("%s", file);
return 0;
}
int display(const char *path, int detail)
{
DIR *dir = NULL;
struct dirent *de = NULL;
int ret;
dir = opendir(path);
if (dir == NULL)
{
/**
* Note: This is not actualy an error!!
* We show the file, but if it does not exist, we will handle it.
*/
display_attr(path);
//display_file_name(path);
//printf("%s", path);
printf("/n");
return 0;
}
else
{
ret = chdir(path);
if (ret != 0)
{
perror("error change dir");
return -1;
}
while ((de=readdir(dir)) != NULL)
{
if (detail)
{
display_attr(de->d_name);
//display_file_name(de->d_name);
//printf("%s ", de->d_name);
printf("/n");
}
else
//display_file_name(de->d_name);
printf("%s ", de->d_name);
}
}
printf("/n");
closedir(dir);
return 0;
}
int main(int argc, char *argv[])
{
if (argc == 1)
display(".", 1); /* current dir */
else if (argc == 2)
display(argv[1], 1); /* the dir you specify */
else
{
printf("Usage: %s [dir|file]/n", argv[0]);
puts("Display file information of the dir you specify./n");
exit(0);
}
return 0;
}
1、实现功能:
类似shell的“ls -al”的输出。默认输出当前目录文件。
可以只简单输出文件名称,需要在程序中的display中第2个参数指定,0为简单输出文件名称。
也可将文件名称作为参数,程序会显示了该文件的相应信息,如果文件无效(不存在),由perror处理。
2、未完成:
a、对文件名称不作排序;
b、对main输入参数作简单处理,不涉及复杂的参数处理。
c、格式输出不理想。对于长度不确定的,如用户名或文件大小等等,只大致估计其长度,如用户名为8,文件大小为5,等等。未深入了解shell的ls实现,它的输出格式就很漂亮了,但个人觉得用自己实现起来很麻烦。
d、链接文件的真实文件名称不知道如何处理,暂时未找到资料。
3、学习到的:
详细了解了stat结构体的st_mode格式,文件的类型、权限信息均由此成员确定。经gdb调试,如果以八进制输出数据,将有利于理解程序中的处理方法。
如一个可能的例子为
0120744(八进制)
输出效果为lrwxrw-rw-。其中开头的0表示八进制,l表示其为链接文件,rwx分别表示读、写、可执行。八进制后面三们分别表示用户、与用户同组用户、其它用户的权限,以二进制表示,恰好为3位。如无此相应权限,以“-”表示。具体定义请man stat。
注:在处理权限时就使用到了这个技巧。
注意月份格式输出的“%02d”之类的,这样就能输入月份、日期前面的“0”了。
另外,发现学习Linux的命令时,最好在纸上作笔记,因为这样才是我们真正需要的命令。比看网上的教程高效多了。
补:其实这个程序有一些多余的代码,因为在opendir返回的de中已经得到了文件名了,存放de->d_name中,所以可以不在再在这个“路径”中查找文件名称了,直接指定它,或者直接输出它就可以了。现将程序作小小改动。过了一天才发现这个问题,惭愧啊!
相关文章推荐
- 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。
- 实现一个简单的菜单程序,运行时显示"Menu:A(dd) D(elete) S(ort) Q(uit),Select one: "提示用户输入。输入A、D、S时分别提示"数据已经增加、删除、排序"
- 自己写了一个链表功能还不完善但是简单的增删改查功能都已经实现了
- 用MASM写一个简单的实现递归操作的汇编程序,所谓递归,上课已经跟大家说清楚了,如果我们只考虑简单的只分一次的递
- 笔记1-1: 实现一个简单的ls列出目录中的所有项目的程序
- XHTML 的一个实例, 其实这个实例的方法已经可以实现所有要实现的布局. by Emerald 绿色学院 - Green Institute
- 看着网上有进制转换的计算器,想做着试试(只需一个简单的方法即可实现)
- 用Python 实现刷钻网上抢任务,并实现一个简单的限制使用时间的功能
- 实现一个简单的ls命令
- unix ls命令的一个简单实现
- XHTML 的一个实例, 其实这个实例的方法已经可以实现所有要实现的布局. by Emerald 绿色学院 - Green Institute
- 实现一个简单的ls命令
- 列出文件名和属性——实现一个简单的ls命令
- 网上一堆代码,没有一个真正实现curl传图片成功过的,这儿,我来个成功的,超级简单,扩展性强【广告一下】
- unix ls命令的一个简单实现
- 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。
- 使用简单的jqury实现幻灯片效果(有很多问题,先记下来)
- 一个简单的用户登录接口asp实现
- Gtest源码剖析:1.实现一个超级简单的测试框架xtest
- Winform编程总结1—从网上找到一个winform控件,实现打开word的功能