如何在 Linux 系统上列出重复的文件名
- 忽略案件
- 包括所有子目录
文件不应该按它们的不同进行比较内容但只能通过他们的名字。输出应该是包含路径的文件名列表,以便可以对这些文件运行进一步的命令。
假设我们有
ls -1R /tmp/
foo
BAR
barfoo
a/BAr
a/b/bar
c/bAr
过滤/查找脚本的输出应该是
/tmp/BAR
/tmp/a/BAr
/tmp/a/b/bar
/tmp/c/bAr
答案1
find . -printf "%p %f\n" | sort -f -k2 | uniq -Di -f1
find
如果您不想从以下位置开始,请指定您选择的起始目录.
。-type f
如果您只想添加文件名称。
- 该
find
命令按目录顺序(即,就您而言,随机顺序)生成文件(和目录)名称列表。 -printf "%p %f\n"
打印完整路径名(相对于.
)和文件名。sort -f
是 的缩写sort --ignore-case
,即,它以不区分大小写的方式对文件名列表进行排序-k2
告诉它使用第二个字段作为排序键。uniq -Di -f1
是 的缩写,即,它根据第二个字段及其他字段(即具有相同(不区分大小写)的文件名)的不区分大小写的比较,uniq --all-repeated --ignore-case --skip-fields=1
显示重复出现的(所有)输出行。find
这应该会为您提供所需的输出,但每行末尾都会重复文件名。如果你想摆脱它,请输入sed 's/ .*//'
.
一些问题:
如果你有目录它们的名称除了大小写之外都相同,并且它们包含名称除了大小写之外都相同的文件,例如,
documents/design.doc Documents/Design.doc
然后这些将被列出。
如果您的文件(或目录)的名称包含空格、制表符或换行符,则会中断。
答案2
这适用于基本文件名,但不适用于带有回车符和可能其他一些边缘情况的文件。
FilesNoPath=$(find . -printf "%f\n")
FilesWithPath=$(find .)
oldIFS=$IFS
IFS=$'\n'
for filename in $FilesNoPath;
do
Matches=$(echo "$FilesWithPath" | grep -i "/$filename$")
if [ $(echo "$Matches" | wc -l) -gt 1 ]
then
echo Found matches:
echo "$Matches"
FilesWithPath=$(echo "$FilesWithPath" | grep -vi "/$filename$")
fi
done
IFS=$oldIFS
如果您希望输出显示完整路径和/或您不想从匹配文件的父目录中执行此命令,则可以将.
两个 find 命令中的替换为 。/path/to/your/files