执行两次代码,打印出两次执行过程中新增的文件及删除的文件
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#define RECORD_PATH "record.bk"
int ListDir(const char *pdirname, FILE *file) //遍历指定目录下的所有文件和子目录,并将文件路径写入到指定的文件中
{
DIR *dp = NULL;
struct dirent *pp = NULL;
char tmpbuff[1024] = {0};
dp = opendir(pdirname);
if (NULL == dp)
{
perror("fail to opendir");
return -1;
}
while (1)
{
pp = readdir(dp);
if (NULL == pp)
{
break;
}
if ('.' == pp->d_name[0])
{
continue;
}
sprintf(tmpbuff, "%s/%s", pdirname, pp->d_name);
fprintf(file, "%s\n", tmpbuff);
if (DT_DIR == pp->d_type)
{
ListDir(tmpbuff, file);
}
}
closedir(dp);
return 0;
}
int ListDirToRecord(const char *pdirname)//使用ListDir函数遍历指定目录,并将结果写入到名为record.bk的文件中。
{
FILE *fp = NULL;
fp = fopen(RECORD_PATH, "w");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
ListDir(pdirname, fp);
fclose(fp);
return 0;
}
int ShowDeleteFiles(void)//打开record.bk文件,读取其中的文件路径,并判断这些文件是否存在于文件系统中。如果不存在,则打印这些文件路径,即表示这些文件已被删除
{
FILE *fp = NULL;
char tmpbuff[4096] = {0};
char *pret = NULL;
fp = fopen(RECORD_PATH, "r");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
while (1)
{
pret = fgets(tmpbuff, sizeof(tmpbuff), fp);
if (NULL == pret)
{
break;
}
tmpbuff[strlen(tmpbuff)-1] = '\0';
if (access(tmpbuff, F_OK) != 0)
{
printf("%s\n", tmpbuff);
}
}
fclose(fp);
return 0;
}
int IsNewFile(char *pfilepath)//判断指定的文件路径是否在record.bk中存在。如果存在,则返回0,表示不是新文件;如果不存在,则返回1,表示是新文件
{
FILE *fp = NULL;
char tmpbuff[4096] = {0};
char *pret = NULL;
fp = fopen(RECORD_PATH, "r");
if (NULL == fp)
{
perror("fail to fopen");
return -1;
}
while (1)
{
pret = fgets(tmpbuff, sizeof(tmpbuff), fp);
if (NULL == pret)
{
break;
}
tmpbuff[strlen(tmpbuff)-1] = '\0';
if (0 == strcmp(tmpbuff, pfilepath))
{
fclose(fp);
return 0;
}
}
fclose(fp);
return 1;
}
int ListDir2(const char *pdirname)//用于遍历指定目录下的所有文件和子目录,并判断每个文件路径是否为新文件(调用IsNewFile函数)。如果是新文件,则打印该文件路径。
{
DIR *dp = NULL;
struct dirent *pp = NULL;
char tmpbuff[1024] = {0};
dp = opendir(pdirname);
if (NULL == dp)
{
perror("fail to opendir");
return -1;
}
while (1)
{
pp = readdir(dp);
if (NULL == pp)
{
break;
}
if ('.' == pp->d_name[0])
{
continue;
}
sprintf(tmpbuff, "%s/%s", pdirname, pp->d_name);
if (IsNewFile(tmpbuff))
{
printf("%s\n", tmpbuff);
}
if (DT_DIR == pp->d_type)
{
ListDir2(tmpbuff);
}
}
closedir(dp);
return 0;
}
int ShowNewFiles(const char *pdirname)//调用ListDir2函数遍历指定目录,然后打印所有新文件的路径
{
ListDir2(pdirname);
return 0;
}
int main(void)//首先检查是否存在record.bk文件,如果存在,则调用ShowDeleteFiles函数打印已删除的文件路径,然后调用ShowNewFiles函数打印新增的文件路径。如果record.bk文件不存在,则调用ListDirToRecord函数生成该文件
{
int ret = 0;
ret = access(RECORD_PATH, F_OK);
if (0 == ret)
{
printf("删除的文件:\n");
ShowDeleteFiles();
printf("新增的文件:\n");
ShowNewFiles(".");
}
else
{
ListDirToRecord(".");
}
return 0;
}
一、时间获取
1.time
time_t time(time_t *tloc);
功能:
返回1970-1-1到现在的秒数(格林威治时间)
参数:
tloc:存放秒数空间首地址
返回值:
成功返回秒数
失败返回-1
2.localtime
struct tm *localtime(const time_t *timep);
功能:
将秒数转换为本地时间
参数:
timep:存放秒数空间首地址
返回值:
成功返回结构体时间
失败返回NULL
struct tm {
int tm_sec; /* Seconds (0-60) */
int tm_min; /* Minutes (0-59) */
int tm_hour; /* Hours (0-23) */
int tm_mday; /* Day of the month (1-31) */
int tm_mon; /* Month (0-11) */
int tm_year; /* Year - 1900 */
int tm_wday; /* Day of the week (0-6, Sunday = 0) */
int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */
int tm_isdst; /* Daylight saving time */
};
3.mktime
time_t mktime(struct tm *tm);
功能:
将本地时间转换为秒数
获取前一天的日期和时间
#include "head.h"
int main(void)
{
time_t t;
struct tm *ptm = NULL;
struct tm tmp;
tmp.tm_year = 2024-1900;
tmp.tm_mon = 2-1;
tmp.tm_mday = 20;
tmp.tm_hour = 11;
tmp.tm_min = 22;
tmp.tm_sec = 30;
t = mktime(&tmp);
t -= 86400; //。通过 t -= 86400 对时间值进行减去一天的秒数的操作。
// time(&t);
ptm = localtime(&t);
printf("%04d-%02d-%02d %02d:%02d:%02d\n", ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
return 0;
}
二、文件属性和权限的获取:
1.stat
int stat(const char *pathname, struct stat *statbuf);
功能:
将pathname对应的文件信息放入statbuf中
参数:
pathname:文件路径字符串的首地址
statbuf:存放文件信息空间的首地址
返回值:
成功返回0
失败返回-1
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
nlink_t st_nlink; /* Number of hard links */
uid_t st_uid; /* User ID of owner */
gid_t st_gid; /* Group ID of owner */
dev_t st_rdev; /* Device ID (if special file) */
off_t st_size; /* Total size, in bytes */
blksize_t st_blksize; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* Time of last access */
struct timespec st_mtim; /* Time of last modification */
struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
/etc/passwd 口令文件
/etc/group 组信息文件
2.getpwuid
struct passwd *getpwuid(uid_t uid);
功能:
通过UID获得对应的用户信息
参数:
uid:用户的ID号
返回值:
成功返回包含用户信息的结构体
失败返回NULL
struct passwd {
char *pw_name; /* username */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* user information */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
3.getgrgid
struct group *getgrgid(gid_t gid);
功能:
通过组ID获得组信息
参数:
gid:组的ID号
返回值:
成功返回包含组信息的结构体
失败返回NULL
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* NULL-terminated array of pointers
to names of group members */
};
4.readlink
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
功能:
读取连接文件本身的内容
参数:
pathname:链接文件的路径
buf:存放数据空间首地址
bufsiz:最大存放数据字节数
返回值:
成功返回读到字节个数
失败返回-1
获取给定文件的详细信息,并以类似 ls -l
命令的格式进行输出
#include "head.h"
int main(int argc, const char *argv[])
{
struct stat buf;
int ret = 0;
struct passwd *pwd = NULL;
struct group *grp = NULL;
struct tm *ptm = NULL;
char *mon[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
char tmpbuff[1024] = {0};
if (argc != 2)
{
fprintf(stderr, "Usage:./a.out filename\n");
return -1;
}
ret = lstat(argv[1], &buf);
if (-1 == ret)
{
perror("fail to stat");
return -1;
}
#if 0
switch (buf.st_mode & S_IFMT)
{
case S_IFDIR:putchar('d');break;
case S_IFREG:putchar('-');break;
case S_IFSOCK:putchar('s');break;
case S_IFLNK:putchar('l');break;
case S_IFBLK:putchar('b');break;
case S_IFCHR:putchar('c');break;
case S_IFIFO:putchar('p');break;
}
#endif
if (S_ISREG(buf.st_mode))
{
putchar('-');
}
else if (S_ISDIR(buf.st_mode))
{
putchar('d');
}
else if (S_ISCHR(buf.st_mode))
{
putchar('c');
}
else if (S_ISBLK(buf.st_mode))
{
putchar('b');
}
else if (S_ISLNK(buf.st_mode))
{
putchar('l');
}
else if (S_ISSOCK(buf.st_mode))
{
putchar('s');
}
else if (S_ISFIFO(buf.st_mode))
{
putchar('p');
}
buf.st_mode & S_IRUSR ? putchar('r') : putchar('-');
buf.st_mode & S_IWUSR ? putchar('w') : putchar('-');
buf.st_mode & S_IXUSR ? putchar('x') : putchar('-');
buf.st_mode & S_IRGRP ? putchar('r') : putchar('-');
buf.st_mode & S_IWGRP ? putchar('w') : putchar('-');
buf.st_mode & S_IXGRP ? putchar('x') : putchar('-');
buf.st_mode & S_IROTH ? putchar('r') : putchar('-');
buf.st_mode & S_IWOTH ? putchar('w') : putchar('-');
buf.st_mode & S_IXOTH ? putchar('x') : putchar('-');
printf(" %ld", buf.st_nlink);
pwd = getpwuid(buf.st_uid);
if (NULL == pwd)
{
printf(" %d", buf.st_uid);
}
else
{
printf(" %s", pwd->pw_name);
}
grp = getgrgid(buf.st_gid);
if (NULL == grp)
{
printf(" %d", buf.st_gid);
}
else
{
printf(" %s", grp->gr_name);
}
printf(" %ld", buf.st_size);
ptm = localtime(&buf.st_mtime);
printf(" %s %d %d:%d", mon[ptm->tm_mon], ptm->tm_mday, ptm->tm_hour, ptm->tm_min);
printf(" %s", argv[1]);
if (S_ISLNK(buf.st_mode))
{
readlink(argv[1], tmpbuff, sizeof(tmpbuff));
printf(" -> %s", tmpbuff);
}
putchar('\n');
return 0;
}
三、软连接和硬链接:
1.软连接(符号链接)
通过文件名链接,所有能够看到的连接文件均为软连接文件
ln -s file.txt a.txt
软链接(符号链接):
- 软链接是通过文件名链接,创建一个指向目标文件的链接。
- 软链接文件本身只包含目标文件的路径名,而不是目标文件的实际数据。
- 所有能够看到的连接文件都是软链接。
- 当删除原始文件时,软链接仍然存在,但指向的目标文件将不再可用。
- 创建软链接使用
ln -s
命令,例如:ln -s file.txt a.txt
。
2.硬链接
通过文件对应的inode节点链接
ln file.txt b.txt
硬链接:
- 硬链接是通过文件对应的 inode 节点链接,为同一个文件分配多个文件名。
- 硬链接文件和原始文件具有相同的 inode 节点和相同的索引节点号。
- 修改任何一个硬链接文件(如更改文件的内容),都会影响到其他硬链接文件。
- 可以通过不同的文件名访问同一个文件的内容。
- 当删除一个硬链接文件时,原始文件和其他硬链接文件仍然存在。
- 创建硬链接使用
ln
命令,例如:ln file.txt b.txt
。