如何在给定目录中找到重复的文件名(递归)?BASH

yak*_*yak 8 bash filenames duplicates

我需要在给定的目录树中找到每个重复的文件名.我不知道,dir tree用户将作为脚本参数给出什么,所以我不知道目录层次结构.我试过这个:

#!/bin/sh
find -type f | while IFS= read vo
do
echo `basename "$vo"`
done
Run Code Online (Sandbox Code Playgroud)

但这不是我想要的.它只找到一个重复,然后结束,即使,如果有更多的重复文件名,它也 - 它不打印整个路径(只打印文件名)和重复计数.我想做一些类似于这个命令的事情:

find DIRNAME | tr '[A-Z]' '[a-z]' | sort | uniq -c | grep -v " 1 " 
Run Code Online (Sandbox Code Playgroud)

但它对我有用,不知道为什么.即使我有重复项,也不会打印任何内容.我使用的是Xubuntu 12.04.

psi*_*bar 12

这是另一个解决方案(基于@ jim-mcnamara的建议)没有awk:

解决方案1

#!/bin/sh 
dirname=/path/to/directory
find $dirname -type f | sed 's_.*/__' | sort|  uniq -d| 
while read fileName
do
find $dirname -type f | grep "$fileName"
done
Run Code Online (Sandbox Code Playgroud)

但是,您必须进行两次相同的搜索.如果您必须搜索大量数据,这可能会变得非常慢.将"查找"结果保存在临时文件中可能会提供更好的性能.

解决方案2(带临时文件)

#!/bin/sh 
dirname=/path/to/directory
tempfile=myTempfileName
find $dirname -type f  > $tempfile
cat $tempfile | sed 's_.*/__' | sort |  uniq -d| 
while read fileName
do
 grep "$fileName" $tempfile
done
#rm -f tempfile
Run Code Online (Sandbox Code Playgroud)

由于在某些情况下您可能不想在硬盘驱动器上编写临时文件,因此您可以选择符合您需求的方法.两个示例都打印出文件的完整路径.

这里有额外的问题:是否可以将find命令的整个输出保存为变量列表?


jim*_*ara 8

#!/bin/sh
dirname=/path/to/check
find $dirname -type f | 
while read vo
do
  echo `basename "$vo"`
done | awk '{arr[$0]++; next} END{for (i in arr){if(arr[i]>1){print i}}}  
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一下,这个解决方案只告诉你文件名,没有它们所在的路径。我以为这是一个要求 (2认同)

trs*_*trs 7

是的,这是一个非常古老的问题.但所有这些循环和临时文件似乎有点麻烦.

这是我的1行答案:

find /PATH/TO/FILES -type f -printf '%p/ %f\n' | sort -k2 | uniq -f1 --all-repeated=separate
Run Code Online (Sandbox Code Playgroud)

它有它的局限性,由于uniqsort:

  • 在文件名中没有空白(空格,制表符)(将被解释为新的字段uniqsort)
  • 需要文件名打印为空格分隔的最后一个字段(uniq不支持只比较1个字段,并且字段分隔符不灵活)

但它的输出非常灵活,这find -printf对我来说非常有用.似乎也是@yak最初尝试实现的目标.

展示您对此的一些选择:

find  /PATH/TO/FILES -type f -printf 'size: %s bytes, modified at: %t, path: %h/, file name: %f\n' | sort -k15 | uniq -f14 --all-repeated=prepend
Run Code Online (Sandbox Code Playgroud)

也有在选项sortuniq忽略大小写(如主题开罐器旨在通过管道通过来实现tr).使用man uniq或查找它们man sort.