ls
判断是否有路径参数
optind初值为1,读取一个选项+1(包括选项所带的参数和错误的选项).每个选项字符后可以跟一个冒号字符(:),表示这个选项带有一个参数。
函数返回读取的选项,错误返回(?),optind存储每次读取的选项(包括错误的)。
检测到一个选项就把该选项的值(全局变量)变为1。
选项-l
把readdir()的返回值作为参数传给ls_l(),调用stat()。
把stat结构体中的st_mode和以上常量相与(&),输出文件的类型和权限位。
把stat结构体中的st_uid传入getpwuid()获取输出struct passwd中的pw_name。同理也可获得组名。
其余信息也都在stat结构体中,时间用ctime()按格式输出
选项-r
在函数内重新调用函数进行递归,即可倒序输出。
选项-i
调用stat(),输出struct stat 中的 st_ino。
选项-s
调用stat(),输出struct stat 中的 st_blocks。
(我的是512字节一块所以输出时除2)
选项-R
遍历完一个目录后,后用rewinddir()再遍历一次如果文件名是“.”或"…“时continue。其他的用stat()获得的st_mode 判断文件类型,如果是目录则chdir()改变工作目录,递归调用opendir(”.“),调用完后chdir(”. .")再返回上一级目录。
选项-a
a=0时,如果文件名为".“或”. ."或第一个字符为’.',continue。
选项-t
先遍历一遍,得到该目录下一共有几个文件,新建一个结构体包括st_mtime和struct dirent *ent,动态分配相应大小的内存。然后rewinddir()在遍历一遍,把st_mtime和struct dirent *ent存入结构体数组。用qsort()给它降序排序。
遇到的问题
1.qsort()
我写的qsort() 和cmp()应该是没问题的,但就是没排序,不得已用网上找的冒泡。(是Linux自带的头文件有问题吗??)
2.局部变量全局变量名相同
表示选项-i的全局变量i和循环变量i相同,导致不明意义的输出i节点号。
3.malloc()完之后要free()
不然会段错误 或"malloc(): corrupted top size"。
4.cv后记得改变量名
从别的函数cv过来后变量没有改为该函数内对应的变量名。
5.在chdir()后应opendir(“.”)
改变工作目录后又打开了工作目录的名字: “. .”(或是含路径的参数)会输出错误的路径里的内容。
以下为代码实现
#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>
typedef struct t{
time_t time;
struct dirent * Ent;
}file;
int a,l,t,r,i,s,R,R0;
//long long int blocks;
int cmp(const void *a,const void *b);
void ls_t(DIR *dir);
void ls_R(struct dirent *ent);
int ls_s(struct dirent *ent);
void ls_l(struct dirent *ent);
void ls_read(DIR *dir);
void ls_open(char *dir_path);
void Bubble_sort(file list[],int N);
void Bubble_sort(file list[],int N){
int i, j;
file t;
// N 娑擃亜鍘撶槐鐙呯礉闁秴宸� N-1 濞嗭拷
for (i = 0; i < N - 1; i++) {
// 娴犲海顑� 1 娑擃亜鍘撶槐鐘茬磻婵浜堕崢鍡礉闁秴宸婚懛锟� N-1-i
for (j = 0; j < N - 1 - i; j++) {
//濮f棁绶� list[j] 閸滐拷 list[j+1] 閻ㄥ嫬銇囩亸锟�
if (list[j].time < list[j + 1].time) {
//娴溿倖宕� 2 娑擃亜鍘撶槐鐘垫畱娴e秶鐤�
t = list[j];
list[j] = list[j + 1];
list[j + 1] = t;
}
}
}
}
int cmp(const void *a,const void *b){
file *aa=(file *)a;
file *bb=(file *)b;
return (bb->time-aa->time);
}
//时间顺序
void ls_t(DIR *dir){
int mount=0;
struct dirent *ent;
while ((ent = readdir(dir)) != NULL) {
mount++;
}
file *fil=(file *)malloc((mount)*sizeof(file));
mount=0;
rewinddir(dir);
int t=0;
while((ent = readdir(dir)) != NULL){
struct stat statbuf;
stat(ent->d_name,&statbuf);
fil[t].time=statbuf.st_mtime;
fil[t].Ent=ent;
t++;
}
Bubble_sort(fil,t);
// for(int i=0;i<t;i++){
// printf("%lu ",fil[i].time);
// }
// printf("\n");
// //qsort(fil,t,sizeof(file),cmp);//为什么不排序
// for(int i=0;i<t;i++){
// printf("%lu ",fil[i].time);
// }
int blocks=0;
if(r==0){
for(int i1=0;i1<t;i1++){
if(a==0){
if(strcmp(fil[i1].Ent->d_name,".")==0||strcmp(fil[i1].Ent->d_name,"..")==0||fil[i1].Ent->d_name[0]=='.')
continue;
}
if(i==1){
//没有选项-i但会在循环到ls.c时//在循环时i会不规律递增//循环变量名和-i选项重叠
printf("%lu ",fil[i].Ent->d_ino);
}
if(s==1){
blocks+=ls_s(fil[i1].Ent);
}
if(l==1){
ls_l(fil[i1].Ent);
}
printf("%s ", fil[i1].Ent->d_name);
if(l==1) printf("\n");
}
if(s==1){
printf("\n总用量: %d",blocks);
blocks=0;
}
if(R==1){
if(R0==1) printf(" 结束\n");
if(R0==0) R0=1;
for(int i1=0;i1<t;i1++){
if(a==0&&fil[i1].Ent->d_name[0]=='.') continue;//cv后变量没有改为该函数内对应的变量名
if(strcmp(fil[i1].Ent->d_name,".")==0||strcmp(fil[i1].Ent->d_name,"..")==0)
continue;
ls_R(fil[i1].Ent);
}
}
}
if(r==1){
for(int i1=t-1;i1>=0;i1--){
if(a==0){
if(strcmp(fil[i1].Ent->d_name,".")==0||strcmp(fil[i1].Ent->d_name,"..")==0||fil[i1].Ent->d_name[0]=='.')
continue;
}
if(i==1){
printf("%lu ",fil[i1].Ent->d_ino);
}
if(s==1){
blocks+=ls_s(fil[i1].Ent);
}
if(l==1){
ls_l(fil[i1].Ent);
}
printf("%s ", fil[i1].Ent->d_name);
if(l==1) printf("\n");
}
if(s==1){
printf("\n总用量: %d",blocks);
blocks=0;
}
if(R==1){
if(R0==1) printf(" 结束\n");
if(R0==0) R0=1;
for(int i1=0;i1<t;i1++){
if(a==0&&fil[i1].Ent->d_name[0]=='.') continue;
if(strcmp(fil[i1].Ent->d_name,".")==0||strcmp(fil[i1].Ent->d_name,"..")==0)
continue;
ls_R(fil[i1].Ent);
}
}
}
free(fil);
}
//打开子目录
//如果是链接,不打开???
void ls_R(struct dirent *ent){
struct stat statbuf;
stat(ent->d_name,&statbuf);
if(S_ISDIR(statbuf.st_mode)){
// &&strcmp(ent->d_name,".")!=0&&strcmp(ent->d_name,"..")!=0
char name[100];
printf("\n%s/%s:\n",getcwd(name,100),ent->d_name);
chdir(ent->d_name);
ls_open(".");
chdir("..");
}
}
//块大小
//改为单个目录大小
int ls_s(struct dirent *ent){
struct stat statbuf;
stat(ent->d_name,&statbuf);
printf("%lu ",statbuf.st_blocks/2);
return statbuf.st_blocks/2;
}
//详细属性
void ls_l(struct dirent *ent){
struct stat statbuf;
stat(ent->d_name,&statbuf);
switch (statbuf.st_mode & S_IFMT)
{
case S_IFREG:
printf("-");
break;
case S_IFCHR:
printf("c");
break;
case S_IFBLK:
printf("b");
break;
case S_IFDIR:
printf("d");
break;
case S_IFIFO:
printf("p");
break;
case S_IFLNK:
printf("l");
break;
case S_IFSOCK:
printf("s");
break;
}
if(statbuf.st_mode&S_IRUSR)printf("r");else printf("-");
if(statbuf.st_mode&S_IWUSR)printf("w");else printf("-");
if(statbuf.st_mode&S_IXUSR)printf("x");else printf("-");
if(statbuf.st_mode&S_IRGRP)printf("r");else printf("-");
if(statbuf.st_mode&S_IWGRP)printf("w");else printf("-");
if(statbuf.st_mode&S_IXGRP)printf("x");else printf("-");
if(statbuf.st_mode&S_IROTH)printf("r");else printf("-");
if(statbuf.st_mode&S_IWOTH)printf("w");else printf("-");
if(statbuf.st_mode&S_IXOTH)printf("x");else printf("-");
struct passwd *pw = getpwuid(statbuf.st_uid);
struct group *gr = getgrgid(statbuf.st_gid);
printf(" %lu %s %s %ld %s",statbuf.st_nlink,pw->pw_name,gr->gr_name,statbuf.st_blksize,ctime(&statbuf.st_mtime));
// free(pw);
// free(gr);
}
void ls_read(DIR *dir){
struct dirent *ent;
int blocks=0;
while ((ent = readdir(dir)) != NULL) {
if(r==1){
ls_read(dir);//while 改掉
}
if(a==0){
if(strcmp(ent->d_name,".")==0||strcmp(ent->d_name,"..")==0||ent->d_name[0]=='.')
continue;
}
if(i==1){
printf("%lu ",ent->d_ino);
}
if(s==1){
blocks+=ls_s(ent);
}
if(l==1){
ls_l(ent);
}
printf("%s ", ent->d_name);
if(l==1) printf("\n");
}
if(s==1){
printf("\n总用量: %d",blocks);
blocks=0;
}
if(R==1){
if(R0==1) printf(" 结束\n");
if(R0==0) R0=1;
rewinddir(dir);
while((ent=readdir(dir))!=NULL){
if(a==0&&ent->d_name[0]=='.') continue;
if(strcmp(ent->d_name,".")==0||strcmp(ent->d_name,"..")==0)
continue;
ls_R(ent);
}
}
}
void ls_open(char *dir_path){
DIR *dir;
if ((dir = opendir(dir_path)) != NULL) {
if(t==1){
ls_t(dir);
}else {
ls_read(dir);
}
closedir(dir);
} else {
perror("打开目录失败");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[]) {
DIR *dir;
struct dirent *ent;
char *dir_path = ".";
int opt,opterr=0;
while ((opt = getopt(argc, argv, "alRtris")) != -1) {
switch (opt) {
case 'a':
a=1;
break;
case 'l':
l=1;
break;
case 'R':
R=1;
break;
case 't':
t=1;
break;
case 'r':
r=1;
break;
case 'i':
i=1;
break;
case 's':
s=1;
break;
case '?':
printf("Unknown option: %c\n", optopt);
break;
}
}
if (optind<argc&&argc!=1){
dir_path=argv[optind];
chdir(dir_path);
}
ls_open(".");//改变工作目录后又打开了工作目录的名字 ".."(含路径的参数)会出错
printf("\n");
return EXIT_SUCCESS;
}