问题描述
我有一个名为 img
的文件夹,这个文件夹有很多级别的 sub-folders,所有这些级别都包含图像。我要将它们导入图像服务器。
通常图像(或任何文件)可以具有相同的名称,只要它们位于不同的目录路径中或具有不同的扩展名。但是,我将它们导入的图像服务器要求所有图像名称都是唯一的(即使扩展名不同)。
例如,图像 background.png
和 background.gif
将不被允许,因为即使它们具有不同的扩展名,它们仍然具有相同的文件名。即使它们在单独的 sub-folders 中,它们仍然需要是唯一的。
所以我想知道是否可以在 img
文件夹中进行递归搜索以查找具有相同名称(不包括扩展名)的文件列表。
有没有可以做到这一点的命令?
最佳方法
find . -mindepth 1 -printf '%h %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | tr ' ' '/'
正如评论所述,这也会找到文件夹。这是将其限制为文件的命令:
find . -mindepth 1 -type f -printf '%p %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | cut -d' ' -f1
次佳方法
FSlint 是一个多功能的重复查找器,包括查找重复名称的功能:
用于 Ubuntu 的 FSlint 包强调图形界面,但正如 FSlint FAQ 中所述,命令行 界面可通过 /usr/share/fslint/fslint/
中的程序获得。使用 --help
选项记录文档,例如:
$ /usr/share/fslint/fslint/fslint --help
File system lint.
A collection of utilities to find lint on a filesystem.
To get more info on each utility run 'util --help'.
findup -- find DUPlicate files
findnl -- find Name Lint (problems with filenames)
findu8 -- find filenames with invalid utf8 encoding
findbl -- find Bad Links (various problems with symlinks)
findsn -- find Same Name (problems with clashing names)
finded -- find Empty Directories
findid -- find files with dead user IDs
findns -- find Non Stripped executables
findrs -- find Redundant Whitespace in files
findtf -- find Temporary Files
findul -- find possibly Unused Libraries
zipdir -- Reclaim wasted space in ext2 directory entries
$ /usr/share/fslint/fslint/findsn --help
find (files) with duplicate or conflicting names.
Usage: findsn [-A -c -C] [[-r] [-f] paths(s) ...]
If no arguments are supplied the $PATH is searched for any redundant
or conflicting files.
-A reports all aliases (soft and hard links) to files.
If no path(s) specified then the $PATH is searched.
If only path(s) specified then they are checked for duplicate named
files. You can qualify this with -C to ignore case in this search.
Qualifying with -c is more restictive as only files (or directories)
in the same directory whose names differ only in case are reported.
I.E. -c will flag files & directories that will conflict if transfered
to a case insensitive file system. Note if -c or -C specified and
no path(s) specifed the current directory is assumed.
用法示例:
$ /usr/share/fslint/fslint/findsn /usr/share/icons/ > icons-with-duplicate-names.txt
$ head icons-with-duplicate-names.txt
-rw-r--r-- 1 root root 683 2011-04-15 10:31 Humanity-Dark/AUTHORS
-rw-r--r-- 1 root root 683 2011-04-15 10:31 Humanity/AUTHORS
-rw-r--r-- 1 root root 17992 2011-04-15 10:31 Humanity-Dark/COPYING
-rw-r--r-- 1 root root 17992 2011-04-15 10:31 Humanity/COPYING
-rw-r--r-- 1 root root 4776 2011-03-29 08:57 Faenza/apps/16/DC++.xpm
-rw-r--r-- 1 root root 3816 2011-03-29 08:57 Faenza/apps/22/DC++.xpm
-rw-r--r-- 1 root root 4008 2011-03-29 08:57 Faenza/apps/24/DC++.xpm
-rw-r--r-- 1 root root 4456 2011-03-29 08:57 Faenza/apps/32/DC++.xpm
-rw-r--r-- 1 root root 7336 2011-03-29 08:57 Faenza/apps/48/DC++.xpm
-rw-r--r-- 1 root root 918 2011-03-29 09:03 Faenza/apps/16/Thunar.png
第三种方法
将其保存到名为 duplicates.py
的文件中
#!/usr/bin/env python
# Syntax: duplicates.py DIRECTORY
import os, sys
top = sys.argv[1]
d = {}
for root, dirs, files in os.walk(top, topdown=False):
for name in files:
fn = os.path.join(root, name)
basename, extension = os.path.splitext(name)
basename = basename.lower() # ignore case
if basename in d:
print(d[basename])
print(fn)
else:
d[basename] = fn
然后使文件可执行:
chmod +x duplicates.py
运行在例如像这样:
./duplicates.py ~/images
它应该输出具有相同 basename(1) 的文件对。用python写的,你应该可以修改它。
第四种方法
我假设您只需要查看这些 “duplicates”,然后手动处理它们。如果是这样,这个 bash4 代码应该按照我的想法做。
declare -A array=() dupes=()
while IFS= read -r -d '' file; do
base=${file##*/} base=${base%.*}
if [[ ${array[$base]} ]]; then
dupes[$base]+=" $file"
else
array[$base]=$file
fi
done < <(find /the/dir -type f -print0)
for key in "${!dupes[@]}"; do
echo "$key: ${array[$key]}${dupes[$key]}"
done
有关关联数组语法的帮助,请参阅 http://mywiki.wooledge.org/BashGuide/Arrays#Associative_Arrays 和/或 bash 手册。