用于查找所有类似命名文件的脚本(仅根据大小写不同?)

时间:2011-06-20 17:07:31

标签: perl bash case-sensitive filesize

我一直在使用命令行处理SVN仓库。我现在必须引入需要GUI与repo接口的用户,但这会给类似命名的文件带来许多问题。

由于缺乏沟通或懒惰,大量图片因为原因而被复制。

我希望能够从给定文件夹中递归搜索所有文件,并识别所有仅由大小写/大小写不同的文件,并且必须具有相同的文件大小,因为不同文件之间肯定存在冲突,虽然我还没有遇到过。

我不介意用Perl脚本来处理这个问题,但是我想知道这件事是否已经存在,或者在我卷起袖子之前是否有任何提示?

谢谢:D

7 个答案:

答案 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)

我建议您尝试fdupesduff

答案 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}'