Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Linux中,如何找到存在于同一目录中的同名但情况不同的重复文件?_Linux_Bash_Command Line_Find_Filesystems - Fatal编程技术网

在Linux中,如何找到存在于同一目录中的同名但情况不同的重复文件?

在Linux中,如何找到存在于同一目录中的同名但情况不同的重复文件?,linux,bash,command-line,find,filesystems,Linux,Bash,Command Line,Find,Filesystems,如何返回名为重复的文件列表,即具有相同名称但在不同情况下存在于同一目录中的文件列表 我不在乎文件的内容。我只需要知道任何具有相同名称副本的文件的位置和名称 重复示例: /www/images/taxi.jpg /www/images/Taxi.jpg 理想情况下,我需要从基本目录递归搜索所有文件。在上面的示例中,它是/www/请尝试: ls -1 | tr '[A-Z]' '[a-z]' | sort | uniq -c | grep -v " 1 " 很简单,真的:-)管道不是很棒的野兽吗

如何返回名为重复的文件列表,即具有相同名称但在不同情况下存在于同一目录中的文件列表

我不在乎文件的内容。我只需要知道任何具有相同名称副本的文件的位置和名称

重复示例:

/www/images/taxi.jpg
/www/images/Taxi.jpg
理想情况下,我需要从基本目录递归搜索所有文件。在上面的示例中,它是
/www/

请尝试:

ls -1 | tr '[A-Z]' '[a-z]' | sort | uniq -c | grep -v " 1 "
很简单,真的:-)管道不是很棒的野兽吗

ls-1
每行为您提供一个文件,
tr'[A-Z]'[A-Z]
将所有大写字母转换为小写字母,
sort
对它们进行排序(令人惊讶),
uniq-c
删除随后出现的重复行,同时也为您提供一个计数,最后,
grep-v“1”
去掉计数为1的行

当我在一个有一个“副本”的目录中运行这个时(我将
qq
复制到
qq
),我得到:

对于“this directory and every subdirectory”(此目录和每个子目录)版本,只要将
ls-1
替换为
find.
find DIRNAME
,如果需要特定的目录起点(
DIRNAME
是您想要使用的目录名)

这(对我来说)返回:

这是由于:

pax> ls -1d .gnome2/accels/[bB]* .gconf/system/gstreamer/0.10/audio/profiles/[mM]* [qQ]?
.gconf/system/gstreamer/0.10/audio/profiles/mp3
.gconf/system/gstreamer/0.10/audio/profiles/MP3
.gnome2/accels/blackjack
.gnome2/accels/Blackjack
qq
qQ

更新:

实际上,经过进一步思考,
tr
将把路径的所有组件都小写,以便

/a/b/c
/a/B/c
将被视为重复,即使它们位于不同的目录中

如果您只希望单个目录中的重复项显示为匹配项,则可以使用(非常可怕):

代替:

tr '[A-Z]' '[a-z]'

它所做的只是将路径名的最后部分小写,而不是整个路径名。此外,如果您只需要常规文件(没有目录、FIFO等),请使用
find-typef
来限制返回的内容。

另一个答案很好,但不是我建议的“相当可怕”的perl脚本

perl -pe 's!([^/]+)$!lc $1!e'
它将仅将路径的文件名部分小写

编辑1:事实上,整个问题可以通过以下方式解决:

find . | perl -ne 's!([^/]+)$!lc $1!e; print if 1 == $seen{$_}++'

编辑3:我发现了一个使用sed、sort和uniq的解决方案,该解决方案也将打印出副本,但它仅在文件名中没有空格时才起作用:

find . |sed 's,\(.*\)/\(.*\)$,\1/\2\t\1/\L\2,'|sort|uniq -D -f 1|cut -f 1

编辑2:这里有一个较长的脚本,它将打印出名称,它采用stdin上的路径列表,如
find
所示。不那么优雅,但仍然:

#!/usr/bin/perl -w

use strict;
use warnings;

my %dup_series_per_dir;
while (<>) {
    my ($dir, $file) = m!(.*/)?([^/]+?)$!;
    push @{$dup_series_per_dir{$dir||'./'}{lc $file}}, $file;
}

for my $dir (sort keys %dup_series_per_dir) {
    my @all_dup_series_in_dir = grep { @{$_} > 1 } values %{$dup_series_per_dir{$dir}};
    for my $one_dup_series (@all_dup_series_in_dir) {
        print "$dir\{" . join(',', sort @{$one_dup_series}) . "}\n";
    }
}
#/usr/bin/perl-w
严格使用;
使用警告;
我的%dup\u系列\u每个\u目录;
而(){
我的($dir,$file)=m!(.*/)?([^/]+?)$!;
push@{$dup_series_per_dir{$dir | | |'./'}{lc$file},$file;
}
对于我的$dir(排序键%dup\u series\u per\u dir){
我的@all_dup_series_in_dir=grep{{{$}>1}值%{$dup_series_per_dir{$dir};
对于我的$one_dup_系列(@all_dup_series_in_dir){
打印“$dir\{”.join(',',sort@{$one_dup_series})。“}\n”;
}
}
我相信

ls | sort -f | uniq -i -d

更简单、更快,并且在mpez0响应之后将给出相同的结果,以递归方式检测,只需将“ls”替换为“find”。 我看到的唯一问题是,如果这是一个正在复制的目录,那么这个目录中的每个文件都有一个条目。需要一些人脑来处理这个过程的输出

但无论如何,你不会自动删除这些文件,是吗

find . | sort -f | uniq -i -d

这是一个很好的小命令行应用程序,名为
findsn
,如果您编译deb包不包含的
fslint
,就会得到它

它可以找到任何同名的文件,而且速度极快,可以处理不同的情况

/findsn --help
find (files) with duplicate or conflicting names.
Usage: findsn [-A -c -C] [[-r] [-f] paths(s) ...]
如果未提供任何参数,将搜索$PATH以查找任何冗余参数 或冲突文件

-A  reports all aliases (soft and hard links) to files.
    If no path(s) specified then the $PATH is searched.
如果只指定了路径,则会检查它们是否存在重复的命名路径 文件夹。您可以在此搜索中使用-C限定此项以忽略大小写。 使用-c进行限定更具限制性,因为只有文件(或目录) 在同一目录中,其名称仅在报告大小写时有所不同。 I.E.-c将标记在传输时会发生冲突的文件和目录 到不区分大小写的文件系统。注意如果指定了-c或-c,以及
假定当前目录未指定任何路径。

以下是如何查找所有重复jar文件的示例:

find . -type f -printf "%f\n" -name "*.jar" | sort -f | uniq -i -d

*.jar
替换为您正在寻找的任何重复文件类型。

这里有一个适合我的脚本(我不是作者)。原文和讨论可在此处找到:

如果find命令不适用于您,您可能需要更改它。比如说

OLD :   find "${1}" -type f | xargs -n 1 basename 
NEW :   find "${1}" -type f -printf "%f\n"
您可以使用:

find -type f  -exec readlink -m {} \; | gawk 'BEGIN{FS="/";OFS="/"}{$NF=tolower($NF);print}' | uniq -c
其中:

  • 查找-类型f

    递归打印所有文件的完整路径

  • -exec readlink-m{}
    获取文件的绝对路径

  • gawk'BEGIN{FS=“/”OFS=“/”}{$NF=tolower($NF);print}

    将所有文件名替换为小写

  • uniq-c

    唯一路径,-c输出重复的计数


我刚刚用CentOS上的fdupes清理了一整堆重复文件

yum install fdupes

这一次有点晚了,但这是我的版本:

find . -type f | awk -F/ '{print $NF}' | sort -f | uniq -i -d
这里我们使用:

  • 查找
    -查找当前目录下的所有文件
  • awk
    -删除文件名的文件路径部分
  • 排序
    -不敏感地排序大小写
  • uniq
    -从管道中找到复制品

  • (受@mpez0-answer和@SimonDowdles对@paxdiablo-answer的评论启发。)

    您可以使用GNU awk检查给定目录中的重复项:

    gawk 'BEGINFILE {if ((seen[tolower(FILENAME)]++)) print FILENAME; nextfile}' *
    
    这用于在继续读取文件之前执行某些操作。在本例中,它跟踪出现在数组
    seen[]
    中的名称,该数组的索引是l中的文件名
    find -type f  -exec readlink -m {} \; | gawk 'BEGIN{FS="/";OFS="/"}{$NF=tolower($NF);print}' | uniq -c
    
    yum install fdupes
    
    find . -type f | awk -F/ '{print $NF}' | sort -f | uniq -i -d
    
    gawk 'BEGINFILE {if ((seen[tolower(FILENAME)]++)) print FILENAME; nextfile}' *
    
    $ tree
    .
    ├── bye.txt
    ├── hello.txt
    ├── helLo.txt
    ├── yeah.txt
    └── YEAH.txt
    
    0 directories, 5 files
    $ gawk 'BEGINFILE {if ((a[tolower(FILENAME)]++)) print FILENAME; nextfile}' *
    helLo.txt
    YEAH.txt