我一直在使用命令行处理SVN仓库。我现在必须引入需要GUI与repo接口的用户,但这会给类似命名的文件带来许多问题。
由于缺乏沟通或懒惰,大量图片因为原因而被复制。
我希望能够从给定文件夹中递归搜索所有文件,并识别所有仅由大小写/大小写不同的文件,并且必须具有相同的文件大小,因为不同文件之间肯定存在冲突,虽然我还没有遇到过。
我不介意用Perl脚本来处理这个问题,但是我想知道这件事是否已经存在,或者在我卷起袖子之前是否有任何提示?
谢谢:D
答案 0 :(得分:3)
我依靠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
答案 1 :(得分:1)
我个人没有使用它,但Duplicate Files Finder看起来很合适。
但是,无论文件名是什么,它都会识别任何重复的文件,因此如果您只想要使用不区分大小写的文件名重复,则可能必须过滤结果。
它是开源的,可在Windows和Linux上使用,同时具有命令行和GUI界面,从描述中算法听起来非常快(仅比较具有相同大小的文件,而不是为每个文件生成校验和)。 / p>
答案 2 :(得分:1)
据我所知,你想要什么并不存在。但是,这是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
编辑:添加了评论,并且受到TLP评论的启发,仅使路径的文件部分成为相等比较的重要部分。现在已经测试到了合理的最低程度,我希望它不会在你脸上爆炸。
答案 3 :(得分:1)
我猜它会是这样的:
#!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中不会发生)。另请注意,如果两个文件名相同(案例除外)且大小相同,则只会打印第一个文件。在三个的情况下,只有前两个,依此类推(当然,你需要保留一个!)。
答案 4 :(得分:1)
答案 5 :(得分:0)
这是一个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 ] ) )
答案 6 :(得分:0)
一个shell脚本,用于列出Subversion工作目录中的所有文件名,这些文件名仅与同一目录中的另一个文件名不同,因此会在不区分大小写的文件系统上导致Subversion客户端出现问题,这些文件系统无法区分这些文件名:
find . -name .svn -type d -prune -false -o -print | \ perl -ne 'push @{$f{lc($_)}}, $_; END{map{print @{$f{$_}}} grep {@{$f{$_}}>1} sort keys %f}'