Linux系统编程之——实现ls-l命令

功能描述:

仿写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

你可能感兴趣的:(linux系统编程)