编程语言:C/C++
编程环境:WSL:Ubuntu-20.04
要求:对于给定文件名filePath
,以其为根节点遍历其下包含所有的文件/文件夹,找出硬连接数为2或以上的inode
节点,输出其链接文件名。
思路:
- 通过
scandir
函数递归遍历filePath
下的所有文件/文件夹。 - 使用hash表(
unodered_map
)记录硬链接数大于等于2的节点及其关联文件集合。形式为:<Key:inode号,Value:文件名集合>
。 - 对于每个遍历到的文件/文件夹,获取其绝对路径,利用
stat
函数读取其文件状态信息,检测其硬链接数,如果大于等于2,向对应inode
号的哈希表项值添加文件名。
代码:
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
#include <iostream>
#include <unordered_map>
#define DIRECTORY_TYPE 4
#define REGULAR_TYPE 8
using namespace std;
unordered_map<unsigned long, vector<string>> mp;//记录硬链接数大于等于2的inode信息的hash表
void Scanner(const char *filePath)
{
//通过dirent表和scandir函数获取该目录下的文件/文件夹
struct dirent **name_list;
int n = scandir(filePath, &name_list, 0, alphasort);
if (n < 0)
printf("scandir return %d \n", n);
else
{
//递归遍历用的字符串
char tmpFileName[256] = {0};
int index = 0;
while (index < n)
{
//对于每一个遍历到的文件/文件夹,获取其文件状态信息
struct stat b;
//合成文件/文件夹的绝对路径
memset(tmpFileName, '\0', sizeof(tmpFileName));
strcpy(tmpFileName, filePath);
tmpFileName[strlen(filePath)] = '/';
strcat(tmpFileName, name_list[index]->d_name);
//获取文件状态
stat(tmpFileName, &b);
if (b.st_nlink >= 2)
{
//如果硬链接数大于等于2,向对于哈希表项中添加文件名
mp[b.st_ino].push_back(string(tmpFileName));
}
if (name_list[index]->d_type == DIRECTORY_TYPE && strcmp(name_list[index]->d_name, ".") != 0 && strcmp(name_list[index]->d_name, "..") != 0)
{
//如果文件类型是目录类型(且不是"."和".."),则递归调用Scanner扫描文件夹
Scanner(tmpFileName);
}
//name_list是分配在栈中的,使用完要及时回收
free(name_list[index++]);
}
//回收name_list
free(name_list);
}
return;
}
int main()
{
//扫描,记录相关信息
Scanner("/mnt/d/VS code projects/leetcode");
//遍历map,输出目标inode号和链接文件
for (unordered_map<unsigned long, vector<string>>::iterator it = mp.begin(); it != mp.end(); it++)
{
cout << "INode:" << it->first << " "
<< "Linked File:" << endl;
for (int i = 0; i < it->second.size(); i++)
{
cout << it->second[i] << "\t";
}
cout << endl;
}
}
测试
首先在当前目录/mnt/d/VS code projects/leetcode
(自己指定的)下新建一个文件夹1.txt
,随便编辑其内容:
This is a test file.
然后在终端输入命令:
ln 1.txt 2.txt
这个命令是新建一个文件2.txt
,并将其硬链接到1.txt
上。
输入命令:
stat 1.txt
查看文件状态:
File: 1.txt
Size: 20 Blocks: 8 IO Block: 4096 regular file
Device: 32h/50d Inode: 4503599627393775 Links: 2
Access: (0777/-rwxrwxrwx) Uid: ( 1000/ yan) Gid: ( 1000/ yan)
Access: 2022-05-31 22:31:49.885767600 +0800
Modify: 2022-05-31 22:31:49.869438500 +0800
Change: 2022-05-31 22:31:49.869438500 +0800
Birth: -
可以看到此时硬连接数为2。
编译运行上面的程序,控制台输出如下:
INode:4503599627393775 Linked File:
/mnt/d/VS code projects/leetcode/1.txt /mnt/d/VS code projects/leetcode/2.txt
可以看到成功给出了满足要求的inode
号,和硬链接在它上面的所有文件。