支持 -r --recursive 递归处理子目录,-a 显示隐藏文件,-l 显示属性,及这些参数的任意组合,可指定路径,默认为当前目录。
1/**//*
2作者
3 coreBugZJ
4 jinyang6655
5
6命令名
7 ols
8参数
9 递归
10 -r
11 --recursive
12 所有文件
13 -a
14 属性
15 -l
16
17使用方式举例
18 ols
19 ols -r
20 ols dirnameA -ra
21 ols dirnameA dirnameB -l -a
22*/
23
24
25/**//*
26几个定义
27
28fullname /home/dir/name.c
29dirname /home/dir
30fullpath /home/dir/
31filename name.c
32*/
33
34
35#include <stdio.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <dirent.h>
39#include <string.h>
40#include <getopt.h>
41#include <math.h>
42#include <pwd.h>
43#include <grp.h>
44#include <time.h>
45
46 /**//* 文件名最大长度 */
47#define NAME_LEN 257
48
49
50 /**//* 标志位,是否 -r */
51#define FLAG_R 1
52 /**//* 标志位,是否 -a */
53#define FLAG_A 2
54 /**//* 标志位,是否 -l */
55#define FLAG_L 4
56
57
58 /**//* 定义函数类型,独立于文件遍历方式,处理被遍历到的文件或文件夹 */
59typedef void (*DO_CMD_FILE)( const char *dirname, const char *filename, int flag );
60
61
62 /**//*
63 文件遍历,独立于对文件的处理方式,由参数 函数指针决定对遍历到的文件如何处理,
64 flag 中标志位 FLAG_R 是否为 1 决定是否遍历子目录
65 */
66#define QUE_LEN (1024*32)
67char queDirName[ QUE_LEN ][ NAME_LEN ];
68int queHead, queTail;
69
70void do_cmd( const char *dirname, DO_CMD_FILE do_cmd_file, int flag ) {
71 DIR *dir_ptr;
72 struct dirent *dirent_ptr;
73 struct stat info;
74 char dirName[ NAME_LEN ] = "", fullPath[ NAME_LEN ] = "", fullName[ NAME_LEN ] = "";
75
76 queHead = 0;
77 queTail = 1;
78 strcpy( queDirName[ 0 ], dirname );
79
80 while ( queHead != queTail ) {
81 strcpy( dirName, queDirName[ queHead ] );
82 strcpy( fullPath, dirName );
83 strcat( fullPath, "/" );
84 dir_ptr = opendir( dirName );
85 queHead = ( queHead + 1 ) % QUE_LEN;
86 if ( NULL == dir_ptr ) {
87 continue;
88 }
89 printf( "%-32s ---------------------\n", fullPath );
90 while ( NULL != ( dirent_ptr = readdir(dir_ptr) ) ) {
91 strcpy( fullName, fullPath );
92 strcat( fullName, dirent_ptr->d_name );
93 if ( -1 == stat( fullName, &info ) ) {
94 continue;
95 }
96 do_cmd_file( dirName, dirent_ptr->d_name, flag );
97 if ( ! S_ISDIR(info.st_mode) ) {
98 continue;
99 }
100 if ( 0 == strcmp( ".", dirent_ptr->d_name ) ) {
101 continue;
102 }
103 if ( 0 == strcmp( "..", dirent_ptr->d_name ) ) {
104 continue;
105 }
106 strcpy( queDirName[ queTail ], fullName );
107 queTail = ( queTail + 1 ) % QUE_LEN;
108 if ( queTail == queHead ) {
109 fprintf( stderr, "error : buffer is full !\n" );
110 break;
111 }
112 }
113 closedir( dir_ptr );
114 printf( "\n" );
115 if ( 0 == (flag & FLAG_R) ) {
116 break;
117 }
118 }
119}
120
121
122 /**//* 由模式得到字符串 */
123char* mode2str( int mode );
124 /**//* 由 uid 得到名字 */
125char* uid2name( uid_t uid );
126 /**//* 由 gid 得到名字 */
127char* gid2name( gid_t gid );
128
129
130 /**//* 处理遍历到的文件或文件夹,由 flag 标志位决定处理方式 */
131void do_ls_file( const char *dirname, const char *filename, int flag ) {
132 struct stat inf;
133 char fullName[ NAME_LEN ], modstr[ 13 ];
134 if ( ('.' == filename[ 0 ]) && (0 == (FLAG_A & flag)) ) {
135 return;
136 }
137 if ( 0 == (FLAG_L & flag) ) {
138 printf( "%s\n", filename );
139 return;
140 }
141 strcpy( fullName, dirname );
142 strcat( fullName, "/" );
143 strcat( fullName, filename );
144 if ( -1 == stat( fullName, &inf ) ) {
145 return;
146 }
147 printf( "%s ", mode2str(inf.st_mode) );
148 printf( "%5d ", (int)(inf.st_nlink) );
149 printf( "%-8s ", uid2name(inf.st_uid) );
150 printf( "%-8s ", gid2name(inf.st_gid) );
151 printf( "%8ld ", (long)(inf.st_size) );
152 printf( "%.12s ", ctime(&(inf.st_mtime)) );
153 printf( "%s\n", filename );
154}
155
156
157void do_ls( const char *dirname, int flag ) {
158 do_cmd( dirname, do_ls_file, flag );
159}
160
161
162 /**//* 解析命令参数,设置 flag 标志位 */
163int main( int argc, char *argv[] ) {
164 struct option longopts[] = {
165 { "recursive", 0, NULL, 'r' },
166 { NULL, 0, NULL, 0 }
167 };
168 char *shortopts = "ral";
169
170 int ac = argc, opt, i, flag = 0, cur = 1;
171 char **av = argv;
172 for ( ; ; ) {
173 opt = getopt_long( ac, av, shortopts, longopts, NULL );
174 if ( -1 == opt ) {
175 break;
176 }
177 switch ( opt ) {
178 case 'r' :
179 flag |= FLAG_R;
180 break;
181 case 'a' :
182 flag |= FLAG_A;
183 break;
184 case 'l' :
185 flag |= FLAG_L;
186 break;
187 case ':' :
188 printf( "error !\n" );
189 break;
190 case '?' :
191 printf( "\nusage:\nols\nols -lar\nols /tmp\nols /tmp /usr --recursive\n" );
192 return 0;
193 }
194 }
195
196 for ( i = 1; i < argc; ++i ) {
197 if ( '-' != argv[ i ][ 0 ] ) {
198 do_ls( argv[ i ], flag );
199 cur = 0;
200 }
201 }
202 if ( cur ) {
203 do_ls( ".", flag );
204 }
205
206 return 0;
207}
208
209
210char* mode2str( int mode ) {
211 static char str[ 20 ];
212
213 strcpy( str, "----------" );
214
215 if ( S_ISDIR(mode) ) str[ 0 ] = 'd';
216 if ( S_ISCHR(mode) ) str[ 0 ] = 'c';
217 if ( S_ISBLK(mode) ) str[ 0 ] = 'b';
218
219 if ( mode & S_IRUSR ) str[ 1 ] = 'r';
220 if ( mode & S_IWUSR ) str[ 2 ] = 'w';
221 if ( mode & S_IXUSR ) str[ 3 ] = 'x';
222
223 if ( mode & S_IRGRP ) str[ 4 ] = 'r';
224 if ( mode & S_IWGRP ) str[ 5 ] = 'w';
225 if ( mode & S_IXGRP ) str[ 6 ] = 'x';
226
227 if ( mode & S_IROTH ) str[ 7 ] = 'r';
228 if ( mode & S_IWOTH ) str[ 8 ] = 'w';
229 if ( mode & S_IXOTH ) str[ 9 ] = 'x';
230
231 return str;
232}
233
234char* uid2name( uid_t uid ) {
235 static char numstr[ 32 ];
236 struct passwd *getpwuid(), *pw_ptr;
237
238 if ( NULL == (pw_ptr = getpwuid(uid)) ) {
239 sprintf( numstr, "%d", uid );
240 return numstr;
241 }
242 return pw_ptr->pw_name;
243}
244
245char* gid2name( gid_t gid ) {
246 static char numstr[ 32 ];
247 struct group *getgrgid(), *grp_ptr;
248
249 if ( NULL == (grp_ptr = getgrgid(gid)) ) {
250 sprintf( numstr, "%d", gid );
251 return numstr;
252 }
253 return grp_ptr->gr_name;
254}
255
256