一、 概述
1.1 ls -l 的作用
- Linux下用于查看对应路径的文件信息(隐藏文件除外),后面跟路径名,不跟则默认查看当前路径下
1.2 文件分布
有四个文件:
- ls-l.c
- fun.c
- ls-l.h
- makefile
1.3 如何编译执行
- 本demo使用的是Makefile,所以把下面所有的文件放在一个文件夹后,在当前路径下的终端输入"make"即可完成编译
- 运行的话,Makefile文件中第一行EXE=“内容”,这个内容就是编译生成的可执行文件,在当前路径下的终端输入 “./内容”即可,
- 本demo生成的可执行文件名为“ls-l”,所以输入“./ls-l”即可
- 同"ls -l",本demo后面可以跟路径,也可以不跟,不跟也是默认查看当前路径下的文件信息
1.4 运行环境
- 本代码是在Linux----ubuntu18.04中运行的,
- 如果报错之类的,可以检查一下是不是环境不同导致
二、 直接上代码
ls-l.c
#include "ls-l.h"
int main(int argc, char const *argv[])
{
char path[128] = "";
if (argc == 1)
strcpy(path, ".");
else
strcpy(path, argv[1]);
get_dir_info_by_dirName(path);
return 0;
}
fun.c
#include "ls-l.h"
// 根据目录名获取目录内容
int get_dir_info_by_dirName(char *s)
{
char name[128] = "";
strcpy(name, s);
// 根据目录名获取目录内容
DIR *dir_p = opendir(name);
if (NULL == dir_p)
{
ERR_MSG("opendir");
}
// 读取目录中的文件
struct dirent *dir_read_p = NULL;
struct stat file_st;
while (1)
{
// 读取文件信息
dir_read_p = readdir(dir_p);
// 读的为空
if (NULL == dir_read_p)
{
// 如果errno更新了,不是0了,说明有错误
if (0 != errno)
{
ERR_MSG("dir_read");
}
break;
}
if ('.' == *dir_read_p->d_name)
{
continue;
}
// 清空文件名,方便重新载入
bzero(name, sizeof(name));
// 载入终端输入的路径
strcpy(name, s);
// 如果当前路径不是以 '/' 结束,那么追加一个 '/' ,方便识别成目录
if ('/' != name[strlen(s) - 1])
{
strcat(name, "/");
}
// 获取当前文件的信息
// 将文件名追加到目录路径后面,然后获取信息
file_st = get_file_info(strcat(name, dir_read_p->d_name));
// 打印文件信息
print_info(&file_st, dir_read_p->d_name);
}
return 0;
}
// 根据文件路径名获取文件信息
struct stat get_file_info(char *name)
{
// 存放文件信息
struct stat st;
// 根据文件名进行绑定
if (-1 != stat(name, &st))
{
return st;
}
printf("%s", __FILE__);
printf("__%d__\n", __LINE__);
perror("stat");
}
// 获取文件类型
char get_file_type(mode_t m)
{
switch (m & S_IFMT)
{
case S_IFBLK:
return 'b';
case S_IFCHR:
return 'c';
case S_IFDIR:
return 'd';
case S_IFIFO:
return 'p';
case S_IFLNK:
return 'l';
case S_IFREG:
return '-';
case S_IFSOCK:
return 's';
default:
printf("unknown?\n");
return 0;
}
}
// 获取文件权限
char *get_file_permission(mode_t *m, char *pre) // mode_t m 是传进来的 st.st_mode
{
char s[4] = "rwx";
for (int i = 0; i < 9; i++)
{
if (((*m) & (0400 >> i)) == 0)
{
pre[i] = '-';
continue;
}
pre[i] = s[i % 3];
}
return pre;
}
// 输出信息
void print_info(struct stat *st, char *name)
{
// 获取文件类型
char type = get_file_type(st->st_mode);
// 获取文件权限
char file_pre[10];
strcpy(file_pre, get_file_permission(&(st->st_mode), file_pre));
// 文件硬链接数
__nlink_t links = st->st_nlink;
// 获取文件所属用户
char *u_name = getpwuid(st->st_uid)->pw_name;
// 获取文件所属组
char *g_name = getgrgid(st->st_gid)->gr_name;
// 获取文件大小
__off_t size = st->st_size;
// 获取文件时间戳,上次修改时间
struct tm *t = localtime(&st->st_mtime);
// 文件名 传进来了
// 输出
printf("%c%s %ld %s %s %9ld %2d月 %2d %2d:%02d %s\n",
type, file_pre, links, u_name, g_name, size,
t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, name);
}
ls-l.h
#ifndef __LS_L_H__
#define __LS_L_H__
#include <my_head.h>
// 根据目录名获取目录内容
int get_dir_info_by_dirName(char *name);
// 获取文件信息
struct stat get_file_info(char *name);
// 获取文件类型
char get_file_type(mode_t m);
// 获取文件权限
char *get_file_permission(mode_t *m, char *pre); // mode_t m 是传进来的 st.st_mode
// 输出信息
void print_info(struct stat *st, char *name);
#endif
makefile
EXE=ls-l
CC=gcc
CFLAGs=-c
OBJs+=ls-l.o
OBJs+=fun.o
all:$(EXE)
$(EXE):$(OBJs)
$(CC) $^ -o $@
%.o:%.c
$(CC) $(CFLAGs) $^ -o $@
clean:
rm *.o ls-l