博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

编写自己的ls命令

Posted on 2014-05-09 14:32  xymaqingxiang  阅读(1061)  评论(0编辑  收藏  举报

····要编写ls命令,首先要了解它能做什么,完成了什么工作,是如何完成这些工作的····


 一、ls命令能做什么?

  我们在命令行输入ls,ls默认找出当前目录中所有文件的文件名,并且按照字典序排序后输出。ls命令有很多参数选项,可以决定ls的输出内容。如果参数是目录,ls列出目录的内容,如果参数是文件,ls列出文件名和属性。
  例如:ls -l
       (每行7个字段,mode+links+owers+group+size+last-modified+name)

  问题在于:

    1.如何列出目录的内容。

    2.如何读取并显示文件的属性。

    3.给出一个名字,如何判断出它是目录还是文件。


 二、ls命令是如何工作的?

  文件和目录被组成一棵目录树结构。目录是一种特殊的文件,其内容是文件和目录的名字。目录是记录的序列,每条记录对应一个文件或子目录,通过readdir来读取目录中的记录,readdir返回一个指向目录的当前记录的指针,记录的类型是struct_dirent。


 三、如何编写ls命令?

  框架:
    mian()
    opendir
    while(readdir)
      print d_name
    closedir


 几个结构体的解析:

1、结构体__dirstream:

struct __dirstream{
         void* __fd;
         char* __data;
         int __entry_data;
         char* __ptr;
         int __entry_ptr;
         size_t __allocation;
         size_t __size;
         __libc_lock_define(,__lock)
};
typedef struct __dirstream DIR;

  DIR结构体类似于FILE,是一个内部结构,以下几个函数用这个内部结构保存当前正在被读取的目录的有关信息。
  Eg: DIR *opendir(const char *parhname);打开文件目录,返回指向DIR 结构体的指针。
     struct dirent *readdir(DIR *dp);
     void rewinddir(DIR *dp);
     int closedir(DIR *dp);
     long telldir(DIR *dp);
     void seekdir(DIR *dp,long loc);

2、结构体 dirent:

struct dirent { 
      ino_t d_ino; /* inode number 索引节点号*/ 
      off_t d_off; /* offset to the next dirent 在目录文件中的偏移*/ 
      unsigned short d_reclen; /* length of this record 文件名长*/ 
      unsigned char d_type; /* type of file; not supported by all file system types文件类型 */ 
      char d_name[256]; /* filename 文件名,最长255字符*/ 
}; 

  目录文件(directory file):这种文件包含了其他文件的名字以及指向与这些文件有关的信息的指针。从此可以看出,dirent不仅仅指向目录,还指向目录中的具体文件。(readdir函数同样也可以读取目录下的文件,这就是证据)
  从上述的定义我们可以看出dirent结构体中存储的有关文件的信息太少,不能满足我们的需求,即dirent只是起到了索引的作用。所以我们要想获得ls -l类似的信息,必须通过stat函数获取。
通过readdir函数读取到文件名并存储到结构体dirent的d_name成员中,然后通过int stat(const *file_name,struct stat *buf)获取文件名为d_name的文件的详细信息,并存储在stat结构体中。

3、结构体 stat:

struct stat { 
     dev_t st_dev; /* ID of device containing file 文件使用的设备号*/ 
     ino_t st_ino; /* inode number 索引节点号*/ 
     mode_t st_mode; /* protection 文件访问权限*/ 
     nlink_t st_nlink; /* number of hard links 文件的硬链接数*/ 
     uid_t st_uid; /* user ID of owner 所有者用户识别号*/ 
     gid_t st_gid; /* group ID of owner 组识别号*/ 
     dev_t st_rdev; /* device ID (if special file) 设备文件的设备号*/ 
     off_t st_size; /* total size, in bytes 以字节为单位的文件容量*/ 
     blksize_t st_blksize; /* blocksize for file system I/O 包含该文件的磁盘块的大小*/ 
     blkcnt_t st_blocks; /* number of 512B blocks allocated 该文件所占的磁盘块*/ 
     time_t st_atime; /* time of last access 最后一次访问该文件的时间*/ 
     time_t st_mtime; /* time of last modification 最后一次修改该文件的时间*/ 
     time_t st_ctime; /* time of last status change 最后一次改变文件状态的时间*/ 
};

 struct stat中的st_mode值各个位代表的含义:

The following flags are defined for the st_mode field:
      /*  是什么类型的文件  */
           S_IFMT     0170000   bit mask for the file type bit fields
           S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO
           S_ISUID    0004000   set UID bit
           S_ISGID    0002000   set-group-ID bit (see below)
           S_ISVTX    0001000   sticky bit (see below)
      /*  是否有可读写权限  */
           S_IRWXU    00700     mask for file owner permissions
           S_IRUSR    00400     owner has read permission
           S_IWUSR    00200     owner has write permission
           S_IXUSR    00100     owner has execute permission
           S_IRWXG    00070     mask for group permissions
           S_IRGRP    00040     group has read permission
           S_IWGRP    00020     group has write permission
           S_IXGRP    00010     group has execute permission
           S_IRWXO    00007     mask for permissions for others (not in group)
           S_IROTH    00004     others have read permission
           S_IWOTH    00002     others have write permission
           S_IXOTH    00001     others have execute permission

 4、结构体passwd :

/* The passwd structure.  */
struct passwd
{
  char *pw_name;          /* Username.  */
  char *pw_passwd;        /* Password.  */
  __uid_t pw_uid;         /* User ID.  */
  __gid_t pw_gid;         /* Group ID.  */
  char *pw_gecos;         /* Real name.  */
  char *pw_dir;           /* Home directory.  */
  char *pw_shell;         /* Shell program.  */
};

 5、结构体group:

/* The group structure.     */
struct group
  {
    char *gr_name;         /* Group name.    */
    char *gr_passwd;       /* Password.    */
    __gid_t gr_gid;        /* Group ID.    */
    char **gr_mem;         /* Member list.    */
  };

 6、结构体tm:

/* Used by other time functions.  */
struct tm
{
  int tm_sec;            /* Seconds.    [0-60] (1 leap second) */
  int tm_min;            /* Minutes.    [0-59] */
  int tm_hour;            /* Hours.    [0-23] */
  int tm_mday;            /* Day.        [1-31] */
  int tm_mon;            /* Month.    [0-11] */
  int tm_year;            /* Year    - 1900.  */
  int tm_wday;            /* Day of week.    [0-6] */
  int tm_yday;            /* Days in year.[0-365]    */
  int tm_isdst;            /* DST.        [-1/0/1]*/

#ifdef    __USE_BSD
  long int tm_gmtoff;        /* Seconds east of UTC.  */
  __const char *tm_zone;    /* Timezone abbreviation.  */
#else
  long int __tm_gmtoff;        /* Seconds east of UTC.  */
  __const char *__tm_zone;    /* Timezone abbreviation.  */
#endif
};

 sunmmary:

如果想获取某目录下(eg:目录a)b文件的详细信息,我们该怎么做?
  1、使用opendir函数打开目录a,返回指向目录a的DIR的结构体c。
  2、调用readdir(c)函数读取目录a下所有的文件(包括目录),返回指向目录a下所有文件的dirent结构体d。
  3、遍历d,调用stat(d->name,stat *e)函数来获取每个文件的详细信息,并存储在stat结构体e中。


 知识点解释:

1、stat得到文件属性:
    int result = stat(char * fname , struct stat * bufp)
    包含在# include <sys/stat.h>,把文件fname的信息复制到指针bufp所指的结构中。

2、将mode模式字段转换成字符:
    st_mode是一个16位的二进制数,文件类型和权限被编码在这个数中。
    字段编码——整数是bit组成的序列,使用八进制简化表示。
    解码——掩码技术(与0做位于)。

3、将用户/组ID转换成字符串:
    etc/passwd文件中包含用户列表(搜索文件繁琐),而且其并没有包含所有的用户(网络计算系统,所有主机通过NIS进行用户身份验证)。
    通过getpwuid来得到完整的用户列表——通过库函数getpwuid来访问用户信息,如果用户信息保存在/etc/passwd中,那么getpwuid就会查找/etc/passwd的内容,如果用户信息在NIS中,getpwuid会从NIS中获取信息。
    getpwuid需要uid作为参数,返回一个指向struct passwd的指针。
    return getpwuid(uid)->pw_name
同理:/etc/group是组列表,通过getgrgid访问组列表。

4、用ctime将time_t类型的修改时间转换成字符串格式:
    char *ctime(const time_t *time);包含于time.h中

5、参数(目录OR某个文件)判断:
    if((st.st_mode & S_IFMT) == S_IFDIR)成立则是目录。

6、排序后输出:
    qsort()函数使用快速排序的例程进行排序,包含于stdlib.h中。
    void qsort(void *base,int nelem,int width,int (*fcmp)(const void *,const void *));
    参数解析:    *base:待排序数组首地址
          nelem:数组中待排序元素数目
          width:各元素占用的空间大小
          *:指向函数的指针,用于确定排序的顺存

qsort参考链接:http://baike.baidu.com/view/982231.htm?fr=aladdin

7、高亮显示:

 文件按照属性显示颜色
        033[mode;foreground;backgroundmhello\033[0m

mode为显示模式:
        0、1、22、4、24、5、25、7、27,分别表示设定颜色、黑体、非黑体、下画线、非下画线、闪烁、非闪烁、翻转、非翻转。

foreground为前景颜色:
        30 (黑色)、31 (红色)、32 (绿色)、33 (黄色)、34 (蓝色)、35 ( 紫红色)、36 (青色)和37 (白色)

background为背景颜色:
        40 (黑色)、41 (红色)、42 (绿色)、43 (黄色)、44 (蓝色)、45 ( 紫红色)、46 (青色)和47 (白色)

 1 样式:
 2 00 — Normal (no color, no bold)
 3 01 — Bold //粗体
 4 
 5 文字颜色
 6 30 — Black //黑色
 7 31 — Red //红色
 8 32 — Green //绿色
 9 33 — Yellow //黄色
10 34 — Blue //蓝色
11 35 — Magenta //洋红色
12 36 — Cyan //蓝绿色
13 37 — White //白色
14 
15 背景颜色
16 40 — Black
17 41 — Red
18 42 — Green
19 43 — Yellow
20 44 — Blue
21 45 — Magenta
22 46 — Cyan
23 47 – White
24 
25 白色: 表示普通文件
26 蓝色: 表示目录
27 绿色: 表示可执行文件
28 红色: 表示压缩文件
29 蓝绿色: 链接文件
30 红色闪烁:表示链接的文件有问题
31 黄色: 表示设备文件
32 灰色: 表示其他文件
ls下高亮显示

 8、获取符号链接:

readlink读取符号链接内容:

  表头文件: #include <unistd.h>

  定义函数:ssize_t readlink(const char *path, char *buf, size_t bufsiz);

          path为符号链接路径
          buf为符号链接内容
          bufsize为要获得内容长度

  函数说明:readlink()会将参数path的符号链接内容存储到参数buf所指的内存空间,返回的内容不是以\000作字符串结尾,但会将字符串的字符数返回,这使得添加\000变得简单。若参数bufsiz小于符号连接的内容长度,过长的内容会被截断,如果 readlink 第一个参数指向一个文件而不是符号链接时,readlink 设 置errno 为 EINVAL 并返回 -1。 readlink()函数组合了open()、read()和close()的所有操作。

  返回值 :执行成功则返回字符串的字符数,失败返回-1, 错误代码存于errno
      执行成功则返回ssize_t
  错误代码:
      EACCESS 取文件时被拒绝,权限不够
      EINVAL 参数bufsiz为负数
      EIO O存取错误
      ELOOP 欲打开的文件有过多符号连接问题
      ENAMETOOLONG 参数path的路径名称太长
      ENOENT 参数path所指定的文件不存在
      ENOMEM 核心内存不足
      ENOTDIR 参数path路径中的目录存在但却非真正的目录
      PHP 5. 3.0 后在windows下可实现。

 

待完成工作:
  1、对于指定目录下信息的显示。
  2、支持参数选项:-R,-u等。


 


 

附注:

 

  1 /* ls2_3.c
  2  * -r -l 
  3  */
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 #include <unistd.h>
  8 #include <sys/types.h>
  9 #include <dirent.h>
 10 #include <sys/stat.h>
 11 #include <time.h>
 12 #include <grp.h>
 13 #include <pwd.h>
 14 
 15 void do_ls_ls(char[]);    //No para
 16 void do_ls(char[],int);   //para 
 17 void dostat(char *);      //file status
 18 void show_file_info( char *, struct stat *);
 19 void mode_to_letters( int , char [] );
 20 char *uid_to_name( uid_t );
 21 char *gid_to_name( gid_t );
 22 
 23 void *emalloc(unsigned),*erealloc(void *, unsigned);
 24 char **namelist = NULL;
 25 int listlen = 0;
 26 int taken = 0;
 27 
 28 //设置显示颜色
 29 int background = 1;
 30 int foreground = 0;
 31 int colormode = 0;
 32 
 33 #define CHUNKLEN 100
 34 
 35 main(int ac, char *av[])
 36 {
 37     int r_flag = 0;
 38     int anyfile = 0;
 39     
 40     struct stat st;
 41     
 42     if ( ac == 1 ) //没有参数
 43     {   
 44         //检查
 45         printf("hello---ac=1\n\n");    
 46         do_ls_ls(".");
 47         printf("hello----ac=1结束\n\n");
 48     }
 49     else
 50         while ( --ac ){
 51             *av++;
 52             if(strcmp("-l",*av) == 0)     //参数为-l,正序输出
 53             {
 54                 r_flag = 0;                
 55                 //检查
 56                 printf("hello---参数为l\n\n");
 57                 do_ls( "." ,r_flag);
 58                 printf("hello---参数为l结束\n\n");
 59             }
 60             else if(strcmp("-r",*av) == 0)     //参数为-r,倒序输出
 61             {    
 62                 //检查
 63                 printf("hello----参数为r\n\n");
 64                 r_flag = 1;
 65                 do_ls( "." ,r_flag);
 66                 printf("hello---参数为r结束\n\n");
 67             }
 68             else if(stat(*av, &st) < 0)
 69             {
 70                 //检查
 71                 printf("hello----参数\n\n");
 72                 perror("stat");
 73                 printf("hello---参数:结束\n\n");
 74             }
 75             else if((st.st_mode & S_IFMT) == S_IFDIR)
 76             {
 77                 //检查
 78                 printf("hello---参数为目录 \n\n");
 79                 display_dir(*av);    
 80                 printf("hello---参数为目录结束\n\n");
 81             }
 82             else
 83             {
 84                 //检查
 85                 printf("hello---参数为某个文件\n\n");
 86                 dostat(*av);
 87                 printf("hello---参数为某个文件结束\n\n");
 88             }
 89                 anyfile = 1;
 90         }
 91 }
 92 
 93 void do_ls_ls( char dirname[] )
 94 {
 95     int i;
 96     DIR        *dir_ptr;        /* the directory */
 97     struct dirent    *direntp;        /* each entry     */
 98 
 99     list_init();
100 
101     if ( ( dir_ptr = opendir( dirname ) ) == NULL )
102         fprintf(stderr,"ls2: cannot open %s\n", dirname);
103     else
104     {
105         while ( ( direntp = readdir( dir_ptr ) ) != NULL )
106         {
107             list_append(direntp->d_name);
108             list_sort(0);
109         //    printf("%s\n", direntp->d_name );
110         }
111         for(i=0;i<taken;i++)
112             printf("%s\n", namelist[i]);
113         //    dostat(namelist[i]);
114         closedir(dir_ptr);
115     }
116     list_finish();
117 }
118 
119 int display_dir(char *dirname)
120 {
121     DIR *dir;
122     struct dirent *dirent;
123     struct stat st;
124     char buf[1024];
125 
126     dir = opendir(dirname);
127     
128     //检查
129     printf("hello---display_dir\n\n");
130     while((dirent = readdir(dir)) != NULL)
131     {
132         strcpy(buf, dirname);
133         strcat(buf, "/");
134         strcat(buf, dirent->d_name);
135         if(stat(buf, &st))
136         {
137             perror("stat");
138             return -1;
139         }
140         if(dirent->d_name[0] != '.')
141              display_file(buf, dirent->d_name);
142     }
143     printf("\nhello---display_dir结束\n\n");
144     closedir(dir);
145 }
146 
147 int display_file(char *path, char *filename)
148 {
149     struct stat st;
150     int i;
151     struct passwd *pw;
152     struct group *gr;
153     struct tm *tm;
154     stat(path, &st);
155     dostat(filename);    
156     return 0;
157 }
158 
159 list_init()
160 {
161     namelist = (char **)emalloc(CHUNKLEN * sizeof(char *));
162     listlen = CHUNKLEN;
163     taken = 0;
164 }
165 
166 list_append(char *str)
167 {
168     char *newstring(char *);
169     char *name = newstring(str);
170     
171     if(taken == listlen){
172         listlen += CHUNKLEN;
173         namelist = (char **)erealloc(namelist,listlen);
174     }
175     namelist[taken++] = name ;
176     
177 }
178 
179 list_finish()
180 {
181     int i;
182     for (i=0;i<taken;i++)
183         free(namelist[i]);
184     free(namelist);
185     taken = listlen = 0;
186 }
187 
188 int comp_increasing(char **p1,char **p2)
189 {
190     return strcmp((char *) *p1,(char *) *p2);
191 }
192 
193 int comp_decreasing(char **p1,char **p2)
194 {
195     return strcmp((char *) *p2,(char *) *p1);
196 }
197 
198 list_sort(int revflag)
199 {
200     qsort((void *)namelist,(size_t)taken,sizeof(char *),(__compar_fn_t)(revflag?comp_decreasing:comp_increasing));
201     
202 }
203 
204 void do_ls( char dirname[] , int reverse )
205 {
206     int i;
207     DIR        *dir_ptr;        /* the directory */
208     struct dirent    *direntp;        /* each entry     */
209 
210     list_init();
211 
212     if ( ( dir_ptr = opendir( dirname ) ) == NULL )
213         fprintf(stderr,"ls2: cannot open %s\n", dirname);
214     else
215     {
216         while ( ( direntp = readdir( dir_ptr ) ) != NULL )
217         {
218             list_append(direntp->d_name);
219             list_sort(reverse);
220         }
221         
222         for(i=0;i<taken;i++)
223             dostat( namelist[i] );
224         
225         closedir(dir_ptr);
226     }
227     list_finish();
228 }
229 
230 char *newstring(char *s)
231 {
232     char *rv = emalloc(1+strlen(s));
233     strcpy(rv,s);
234     return rv;
235 }
236 
237 void *emalloc(unsigned n)
238 {
239     void *rv = malloc(n);
240     if(rv)
241         return rv;
242     fprintf(stderr, "ls2:%s/%s\n","out of memory","");
243 }
244 
245 void *erealloc(void *p,unsigned n)
246 {
247     void *rv = realloc(p,n);
248     if(rv)
249         return rv;
250     fprintf(stderr, "ls2:%s/%s\n","out of memory","");
251 }
252 
253 /*
254  * 获得文件的属性
255   */
256 void dostat( char *filename )
257 {
258     struct stat info;
259 
260     if ( stat(filename, &info) == -1 )        /* cannot stat     */
261         perror( filename );            /* say why     */
262     else                    /* else show info     */
263         show_file_info( filename, &info );
264 }
265 
266 void show_file_info( char *filename, struct stat *info_p )
267 {
268     char    *uid_to_name(), *ctime(), *gid_to_name(), *filemode();
269     void    mode_to_letters();
270         char    modestr[11];
271 
272     mode_to_letters( info_p->st_mode, modestr);
273     
274     printf( "%7d "  , info_p->st_ino );        //i节点号
275     printf( "%s"    , modestr );
276     printf( "%4d "  , (int) info_p->st_nlink);    
277     printf( "%-8s " , uid_to_name(info_p->st_uid) );
278     printf( "%-8s " , gid_to_name(info_p->st_gid) );
279     printf( "%8ld " , (long)info_p->st_size);
280     printf( "%.12s ", 4+ctime(&info_p->st_mtime));
281     printf( "\033[%d;%d;%dm%s\033[0m\n"  , foreground, background, colormode, filename );
282 
283 }
284 
285 void mode_to_letters( int mode, char str[])
286 {
287     strcpy( str, "----------" );           /* default=no perms */
288 
289     if ( S_ISDIR(mode) )  {foreground = 34; str[0] = 'd';}    /* directory?       */
290     if ( S_ISCHR(mode) )  {colormode = 1; foreground = 33; background = 40; str[0] = 'c';}    /* char devices     */
291     if ( S_ISBLK(mode) )  {colormode = 1; foreground = 33; background = 40; str[0] = 'b';}    /* block device     */
292 
293     if ( mode & S_IRUSR ) str[1] = 'r';    /* 3 bits for user  */
294     if ( mode & S_IWUSR ) str[2] = 'w';
295     if ( mode & S_IXUSR ) { if(foreground == 37) foreground = 32; str[3] = 'x';}
296 
297     if ( mode & S_IRGRP ) str[4] = 'r';    /* 3 bits for group */
298     if ( mode & S_IWGRP ) str[5] = 'w';
299     if ( mode & S_IXGRP ) { if(foreground == 37) foreground = 32; str[6] = 'x';}
300 
301     if ( mode & S_IROTH ) str[7] = 'r';    /* 3 bits for other */
302     if ( mode & S_IWOTH ) str[8] = 'w';
303     if ( mode & S_IXOTH ) { if(foreground == 37) foreground = 32; str[9] = 'x';}
304 }
305 
306 char *uid_to_name( uid_t uid )
307 {
308     struct    passwd *getpwuid(), *pw_ptr;
309     static  char numstr[10];
310 
311     if ( ( pw_ptr = getpwuid( uid ) ) == NULL ){
312         sprintf(numstr,"%d", uid);
313         return numstr;
314     }
315     else
316         return pw_ptr->pw_name ;
317 }
318 
319 char *gid_to_name( gid_t gid )
320 {
321     struct group *getgrgid(), *grp_ptr;
322     static  char numstr[10];
323 
324     if ( ( grp_ptr = getgrgid(gid) ) == NULL ){
325         sprintf(numstr,"%d", gid);
326         return numstr;
327     }
328     else
329         return grp_ptr->gr_name;
330 }
自己代码

 

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <dirent.h>
  4 #include <sys/stat.h>
  5 #include <string.h>
  6 #include <unistd.h>
  7 #include <grp.h>
  8 #include <pwd.h>
  9 #include <time.h>
 10 
 11 int display_file(char *path, char *filename)
 12 {
 13     struct stat st;
 14     int i;
 15     struct passwd *pw;
 16     struct group *gr;
 17     struct tm *tm;
 18     stat(path, &st);
 19 
 20     switch(st.st_mode & S_IFMT)    
 21     {
 22     case S_IFREG:  printf("-");    break;
 23     case S_IFDIR:  printf("d");    break;
 24     case S_IFLNK:  printf("l");    break;
 25     case S_IFBLK:  printf("b");    break;
 26     case S_IFCHR:  printf("c");    break;
 27     case S_IFIFO:  printf("p");    break;
 28     case S_IFSOCK: printf("s");    break;
 29     }
 30 
 31     for(i = 8; i >= 0; i--)
 32     {    
 33         if(st.st_mode & (1 << i))
 34         {
 35             switch(i%3)
 36             {
 37             case 2: printf("r"); break;
 38             case 1: printf("w"); break;
 39             case 0: printf("x"); break;
 40             }
 41         }
 42         else
 43             printf("-");
 44     }
 45 
 46     pw = getpwuid(st.st_uid);
 47     gr = getgrgid(st.st_gid);
 48 
 49     printf("%2d %s %s %4ld", st.st_nlink, pw->pw_name, gr->gr_name, st.st_size);
 50 
 51     tm = localtime(&st.st_ctime);
 52     printf(" %04d-%02d-%02d %02d:%02d",tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
 53 
 54     printf(" %s\n", filename);
 55 
 56     return 0;
 57 }
 58 
 59 int display_dir(char *dirname)
 60 {
 61     DIR *dir;
 62     struct dirent *dirent;
 63     struct stat st;
 64     char buf[1024];
 65 
 66     dir = opendir(dirname);
 67     while((dirent = readdir(dir)) != NULL)
 68     {
 69         strcpy(buf, dirname);
 70         strcat(buf, "/");
 71         strcat(buf, dirent->d_name);
 72         if(stat(buf, &st))
 73         {
 74             perror("stat");
 75             return -1;
 76         }
 77 
 78         if(dirent->d_name[0] != '.')
 79             display_file(buf, dirent->d_name);
 80     }
 81 }
 82 
 83 int main(int argc, char **argv)
 84 {
 85     struct stat st;
 86     char buf[1024];
 87 
 88     if(stat(argv[1], &st) < 0)
 89     {
 90         perror("stat");
 91         return -1;
 92     }
 93 
 94     if((st.st_mode & S_IFMT) == S_IFDIR)
 95         display_dir(argv[1]);
 96     else
 97         display_file(argv[1], argv[1]);
 98 
 99     return 0;
100 }
童鞋代码

链接:

ubuntu 编写自己的ls命令http://www.cnblogs.com/lr-ting/archive/2012/06/19/2555207.html

高亮显示:http://www.embedu.org/Column/Column341.htm