仿写ls -l的功能(编写myls_l程序),参数通过命令行传入:
1、获取当前工作目录路径并对该目录实现遍历。
2、仿ls -l以列表形式出当前工作目录下的所有文件(包括子目录)
需显示的文件属性。
- ✓ Linux目录操作方法
– 打开目录、关闭目录- ✓ 读取目录文件
- ✓ Linux文件属性获取
- ✓ 文件属性解析相关的重要数据结构、函数、宏和文件掩码
/*************************************************************************
> File Name: myls.c
> Author: 张泽锋
> Mail: [email protected]
> Created Time: 2019年05月02日 星期四 20时13分38秒
> 功能描述:实现ls -l 命令的功能
************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void myls_l(char *pathname);
int main(int argc, char *argv[])
{
char buf[1024] = ""; //路径名
//
if(argc == 1) //没有输入其他参数时,打开当前目录
{
getcwd(buf, sizeof(buf)); //获得当前路径
myls_l(buf);
}
else //输入要展示的目录
{
myls_l(argv[1]);
int i = 2;
while(i < argc)
{
printf("\n");
myls_l(argv[i]);
i++;
}
}
return 0;
}
void myls_l(char *pathname)
{
DIR *cwd = NULL; //路径文件指针
struct dirent *det = NULL; //记录读到的文件信息
struct stat statbuf = {0}; //记录文件的属性
struct passwd *pwd = NULL; //记录文件所属用户
struct group *grp = NULL; //记录文件所属用户组
struct tm mtm = {0};
chdir(pathname); //!非常重要,否则无法获取文件属性
//printf("%s\n", buf); //输出当前路径
cwd = opendir(pathname); //打开目录
while(NULL != (det = readdir(cwd))) //遍历当前目录
{
if(strncmp(det->d_name, ".", 1))
{
stat(det->d_name, &statbuf);
//st_mode //文件类型
if(S_ISREG(statbuf.st_mode))
printf("-");
else if(S_ISDIR(statbuf.st_mode))
printf("d");
else if(S_ISCHR(statbuf.st_mode))
printf("c");
else if(S_ISBLK(statbuf.st_mode))
printf("b");
else if(S_ISFIFO(statbuf.st_mode))
printf("p");
else if(S_ISLNK(statbuf.st_mode))
printf("l");
else if(S_ISSOCK(statbuf.st_mode))
printf("s");
//st_mode //文件权限
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("-");
//st_nlink //硬链接数
printf("%2ld ", statbuf.st_nlink);
//st_uid //属主
pwd = getpwuid(statbuf.st_uid);
printf("%s ", pwd->pw_name);
//st_gid //属组
grp = getgrgid(statbuf.st_gid);
printf("%s ", grp->gr_name);
//st_size //文件大小
printf("%5ld ", statbuf.st_size);
//st_mtim //最后修改时间
localtime_r(&(statbuf.st_mtime), &mtm);
printf("%d月", mtm.tm_mon + 1);
printf("%4d ", mtm.tm_mday);
printf("%02d:", mtm.tm_hour);
printf("%02d ", mtm.tm_min);
//st_name //文件名
printf("%s\n", det->d_name);
}
}
closedir(cwd); //关闭目录
}
/* //用到的函数原型
*
* char *getcwd(char *buf, size_t size); //获取当前目录
* int chdir(const char *path); //改变当前目录
* DIR *opendir(const char *name); //打开目录
* struct dirent *readdir(DIR *dirp); //读目录内容
* int closedir(DIR *dirp); //关闭目录
*
* int stat(const char *pathname, struct stat *statbuf); //获取文件信息
*
* struct passwd *getpwuid(uid_t uid); //获取用户信息
* struct group *getgrgid(gid_t gid); //获取用户组信息
*/
//用到的数据类型
#if 0
struct dirent
{
#ifndef __USE_FILE_OFFSET64
__ino_t d_ino;
__off_t d_off;
#else
__ino64_t d_ino;
__off64_t d_off;
#endif
unsigned short int d_reclen;
unsigned char d_type;
char d_name[256]; /* We must not include limits.h! */
};
struct stat {
unsigned long st_dev; /* Device. */
unsigned long st_ino; /* File serial number. */
unsigned int st_mode; /* File mode. */
unsigned int st_nlink; /* Link count. */
unsigned int st_uid; /* User ID of the file's owner. */
unsigned int st_gid; /* Group ID of the file's group. */
unsigned long st_rdev; /* Device number, if device. */
unsigned long __pad1;
long st_size; /* Size of file, in bytes. */
int st_blksize; /* Optimal block size for I/O. */
int __pad2;
long st_blocks; /* Number 512-byte blocks allocated. */
long st_atime; /* Time of last access. */
unsigned long st_atime_nsec;
long st_mtime; /* Time of last modification. */
unsigned long st_mtime_nsec;
long st_ctime; /* Time of last status change. */
unsigned long st_ctime_nsec;
unsigned int __unused4;
unsigned int __unused5;
};
/* A record in the user database. */
struct passwd
{
char *pw_name; /* Username. */
char *pw_passwd; /* Hashed passphrase, if shadow database
not in use (see shadow.h). */
__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. */
};
/* 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. */
};
struct timespec {
long ts_sec;
long ts_nsec;
};
//文件属性检测宏:
Because tests of the above form are common, additional macros are defined by POSIX to allow the test of the file type in st_mode to be
written more concisely:
S_ISREG(m) is it a regular file?
S_ISDIR(m) directory?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
The preceding code snippet could thus be rewritten as:
stat(pathname, &sb);
if (S_ISREG(sb.st_mode)) {
/* Handle regular file */
}
S_IRWXU 00700 owner has read, write, and execute permission
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 group has read, write, and execute permission
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 others (not in group) have read, write, and
execute permission
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
#endif