查找所有类似名称文件的脚本(仅区分大小写?)
Posted
技术标签:
【中文标题】查找所有类似名称文件的脚本(仅区分大小写?)【英文标题】:Script to find all similarly named files (differing only by case?) 【发布时间】:2011-06-20 17:07:31 【问题描述】:我一直在仅使用命令行处理 SVN 存储库。我现在必须引入需要 GUI 来与 repo 交互的用户,但是这给类似名称的文件带来了许多问题。
由于缺乏沟通或懒惰,大量图像被复制。
我希望能够从给定文件夹中递归搜索所有文件,并识别所有仅大小写不同的文件,并且必须具有相同的文件大小,因为不同文件之间肯定存在冲突,虽然我还没有遇到过。
我不介意自己编写一个 Perl 脚本来处理这个问题,但是我想知道这样的事情是否已经存在,或者在我卷起袖子之前是否有人有任何提示?
谢谢:D
【问题讨论】:
解决方案应该报告不同文件夹中的重复项,还是只报告同一文件夹中的重复项。例如。/bert/me.gif
不会被视为与/ernie/me.gif
重复(假设文件大小相同)?
【参考方案1】:
对于此类问题,我依靠 md5sum
:
find * -type f | xargs md5sum | sort | uniq -Dw32
如果您使用的是 svn,则需要排除 .svn 目录。这将打印出具有相同内容的路径的所有文件。
如果您真的只想匹配大小写不同的文件,您可以在上述管道中添加更多内容:
find * -type f | xargs md5sum | sort | uniq -Dw32 | awk -F'[ /]' ' print $NF ' | sort -f | uniq -Di
myimage_23.png
MyImage_23.png
【讨论】:
这将显示重复的文件,但不限于名称不同的集合。 对。我正在回答这个问题,对实际问题做出一些假设。我认为 OP 遇到的问题是多个图像或资源已提交给 repo,他们需要整合这些图像或资源。这种方法非常适合。 如果你同意这样的假设,那么 OP 可能更喜欢puzzle-diff 我只希望删除同一目录中大小写不同的文件,以便删除不区分大小写处理文件的系统上的 SVN 错误。不过非常感谢您向我介绍uniq
命令,其中有一个不区分大小写的开关-i
:)【参考方案2】:
列出 Subversion 工作目录中所有文件名的 shell 脚本,这些文件名仅在大小写上与同一目录中的另一个文件名不同,因此会导致 Subversion 客户端在不区分大小写的文件系统上出现问题,这些文件名无法区分这些文件名:
寻找 。 -name .svn -type d -prune -false -o -print | \ perl -ne '推@$flc($_), $_; ENDmapprint @$f$_ grep @$f$_>1 排序键 %f'【讨论】:
【参考方案3】:我没有亲自使用过,但Duplicate Files Finder 看起来很合适。
但是,无论文件名如何,它都会识别任何重复文件,因此如果您只希望文件名不区分大小写的重复项,则可能必须过滤结果。
它是开源的,可在 Windows 和 Linux 上使用,具有命令行和 GUI 界面,从描述中该算法听起来非常快(仅比较大小相同的文件,而不是为每个文件生成校验和)。
【讨论】:
【参考方案4】:我猜应该是这样的:
#!perl
use File::Spec;
sub check_dir
my ($dir, $out) = @_;
$out ||= [];
opendir DIR, $dir or die "Impossible to read dir: $!";
my @files = sort grep /^[^\.]/ readdir(DIR); # Ignore files starting with dot
closedir DIR;
my @nd = map ! -d $_ ? File::Spec->catfile($dir, $_) : () @files;
for my $i (0 .. $#nd-1)
push @$out, $nd[$i]
if lc $nd[$i] eq lc $nd[$i+1]
and -s $nd[$i] == -s $nd[$i+1];
map -d $_ ? &check_dir($_, $out) : () @files;
return $out;
print join "\n", @&check_dir(shift @ARGV), "";
使用前请检查,我无法访问windows机器(这在Un*x中不会发生)。另外,请注意,如果两个文件名称相同(大小写除外)且大小相同,则仅打印第一个文件。在三个的情况下,只有前两个,依此类推(当然,你需要保留一个!)。
【讨论】:
这里没有 Windows 机器,只有 Linux 和 OSX。但是,无论出于何种原因,OSX(版本)上的 SVN 客户端在检出类似命名的文件时遇到问题。【参考方案5】:据我所知,您想要的并不存在。但是,这是 bash 中的一个实现:
#!/bin/bash
dir=("$@")
matched=()
files=()
lc() tr '[:upper:]' '[:lower:]' <<< $* ;
in_list()
local search="$1"
shift
local list=("$@")
for file in "$list[@]" ; do
[[ $file == $search ]] && return 0
done
return 1
while read -r file ; do
files=("$files[@]" "$file")
done < <(find "$dir[@]" -type f | sort)
for file1 in "$files[@]" ; do
for file2 in "$files[@]" ; do
if
# check that the file did not match already
! in_list "$file1" "$matched[@]" &&
# check that the files are not the same file
! [ $(stat -f %i "$file1") -eq $(stat -f %i "$file2") ] &&
# check that the size of the files are the same
[ $(stat -f %z "$file1") = $(stat -f %z "$file2") ] &&
# check that the non-directory part (aka file name) of the two
# files match case insensitively
grep -q $(lc "$file1##*/") <<<$(lc "$file2##*/")
then
matched=("$matched[@]" "$file1")
echo "$file1"
break
fi
done
done
编辑:添加 cmets 并受 TLP 评论的启发,仅将文件部分作为路径的一部分进行相等比较。现在已经在合理的最低程度上进行了测试,我希望它不会在你的脸上爆炸。
【讨论】:
【参考方案6】:我建议尝试fdupes 或duff
【讨论】:
【参考方案7】:这是一个 Ruby 脚本,用于递归搜索仅大小写不同的文件。
#!/usr/bin/ruby
# encoding: utf-8
def search( directory )
set =
Dir.entries( directory ).each do |entry|
next if entry == '.' || entry == '..'
path = File.join( directory, entry )
key = path.upcase
set[ key ] = [] unless set.has_key?( key )
set[ key ] << entry
search( path ) if File.directory?( path )
end
set.delete_if |key, entries| entries.size == 1
set.each do |key, entries|
entries.each do |entry|
puts File.join( directory, entry )
end
end
end
search( File.expand_path( ARGV[ 0 ] ) )
【讨论】:
以上是关于查找所有类似名称文件的脚本(仅区分大小写?)的主要内容,如果未能解决你的问题,请参考以下文章