我有大约 250,000 个文件,它们分布在几个带有子文件夹的文件夹中。正在寻找解决方案,如何在所有文件夹及其子文件夹中查找重复的文件名。我的操作系统是 Ubuntu 22.04,使用bash
。
我更喜欢bash
命令/脚本解决方案。但是,也欢迎提出类似的工具建议fdupes -r
(但检查文件名是否相同,而不是检查其内容)。
关于文件及其名称:
- 所有文件都是图像并具有文件扩展名。
- 文件的内容并不重要并且可能会有所不同。
- 文件的扩展名并不重要并且可能不同。
- 文件名和扩展名的字母大小写不一致。
.
有些文件的文件名中有多个句点。例如:file_Name2.1.png
- 文件扩展名由 3 或 4 个符号组成。例如:
.png
,.JPG
,.jpeg
结构:
目录结构非常简单:./[YEAR]/[MONTH]/[IMAGE_NAME].[EXTENSION]
。例如:
tree -a
.
├── 2022
│ └── 12
│ ├── file1.png
│ └── File2.png
└── 2023
├── 01
│ ├── file1.jpg
│ ├── file3.png
│ └── file4.png
└── 02
├── FILE1.png
├── FILE4.PNG
├── File5.png
└── File6.png
预期结果:
file1
:./2022/12/file1.png ./2023/01/file1.jpg ./2023/02/FILE1.png
file4
:./2023/01/file4.png ./2023/02/FILE4.PNG
答案1
假设您的路径:
- 没有换行符
- 文件名中只有一个句点
您可以使用类似如下的方法:
find . -type f | awk -F / '{
fname = tolower($NF); # Get the filename in lowercase
sub(/\.[^.]*$/, "", fname); # Strip extension
paths[fname] = paths[fname] "\n" $0; # Append full path to existing list of filenames separated by newline
count[fname]++;
} END {
for (fname in paths)
if (count[fname] > 1)
print fname paths[fname] "\n"
}'
答案2
你要求一个 Bash 解决方案,因此@muru 的回答非常棒,但这里有一个 Python 脚本可能会引起您或其他用户的兴趣。
#!/usr/bin/env python
import os
from glob import iglob
import sys
# some simple checks
if len(sys.argv) < 2:
sys.exit("Path is required.")
elif len(sys.argv) > 2:
sys.exit("Too many arguments.")
else:
path = sys.argv[1]
# add files to list recursively
files = [i for i in iglob(path + "/**", recursive=True) if os.path.isfile(i)]
# make list with case-insensitive filenames (all lower)
ifnames = [os.path.splitext(os.path.basename(f))[0].lower() for f in files]
# create a dictionary with case-insensitive filenames as keys and their indexes
# as values
d = {}
for i, f in enumerate(ifnames):
if f in d:
d[f].append(i)
else:
d[f] = [i]
# print the full paths of the duplicate files grouped by case-insensitive
# filenames
for k, v in d.items():
if len(v) > 1:
print()
print(k)
for i in v:
print(files[i])
使用您选择的名称保存脚本后(这里我将使用script.py
),运行以下命令赋予其执行权限(将路径替换为实际路径):
chmod u+x /path/to/script.py
该脚本接受一个参数,即您想要在其中查找重复项的目录(目标目录)的路径,如果提供的参数更多或更少,则会引发错误。
您可以按如下方式运行该脚本:
/path/to/script.py /path/to/target/directory
对于您的示例树结构,脚本将返回:
file1
/path/to/target/directory/2022/12/file1.png
/path/to/target/directory/2023/01/file1.jpg
/path/to/target/directory/2023/02/FILE1.png
file4
/path/to/target/directory/2023/01/file4.png
/path/to/target/directory/2023/02/FILE4.PNG
您也可以使用相对路径。例如,运行:
/path/to/script.py .
将在当前目录中搜索重复项,并且如果它是目标目录,则将返回:
file1
./2022/12/file1.png
./2023/01/file1.jpg
./2023/02/FILE1.png
file4
./2023/01/file4.png
./2023/02/FILE4.PNG