Как найти дубликаты файлов с одинаковым именем, но в другом случае, которые существуют в одном каталоге в Linux?

ifelse векторизован, поэтому, если я правильно понимаю ваш код, вам это не нужно sapply. И я бы не использовал слияние - я бы использовал SQLite или PostgreSQL.

Некоторые примеры данных тоже помогли бы: -)

29
задан fedorqui 24 January 2017 в 09:56
поделиться

3 ответа

Другой ответ велик, но вместо «довольно чудовищного» сценария Perl предполагает

perl -pe 's!([^/]+)$!lc $1!e'

, который будет строчными Просто имена файла части пути.

Отредактируйте 1: на самом деле вся проблема может быть решена с:

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

редактировать 3: я нашел решение, используя SED, сортировка и Uniq, который также будет распечатать дубликаты, но он работает только в том случае, если нет пробелов в Имя имена:

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

Редактировать 2: И вот более длительный скрипт, который распечатает имена, он принимает список путей на stdin, как указано . Найти . Не так элегантно, но все же:

#!/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";
    }
}
38
ответ дан 28 November 2019 в 00:51
поделиться

Попробуйте:

ls -1 | tr '[A-Z]' '[a-z]' | sort | uniq -c | grep -v " 1 "

Просто, действительно :-) не трубопровод чудесные звери?

LS -1 дает вам файлы на строку, TR '[AZ]' '[AZ]' преобразует все прописные в нижний регистр, сортирует сортирует их (удивительно достаточно), UNIQ -C удаляет последующие случаи Дублирующихся строк, давая вам счет и, наконец, GREP -V «1» раздают эти линии, где был один.

Когда я запускаю это в каталоге с одним «дубликом» (я скопировал QQ в QQ ), я получаю:

2 qq

для «этого каталога и каждого подкаталога» Версия, просто заменить LS -1 с Найти. ИЛИ Найти dirname Если вы хотите получить определенную отправную точку каталога ( dirname - это имя каталога, которое вы хотите использовать).

Это возвращает (для меня):

2 ./.gconf/system/gstreamer/0.10/audio/profiles/mp3
2 ./.gconf/system/gstreamer/0.10/audio/profiles/mp3/%gconf.xml
2 ./.gnome2/accels/blackjack
2 ./qq

, которые вызваны:

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

будут считаться дубликатами , даже если они в разных каталогах .

Если вы хотите только дубликаты в одном каталоге, чтобы показать как совпадение, вы можете использовать (скорее чудовищные):

perl -ne '
    chomp;
    @flds = split (/\//);
    $lstf = $f[-1];
    $lstf =~ tr/A-Z/a-z/;
    for ($i =0; $i ne $#flds; $i++) {
        print "$f[$i]/";
    };
    print "$x\n";'

вместо:

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

Что это делает, это только в нижнем регистре последняя часть пути. а не все это. Кроме того, если вы хотите только регулярные файлы (никаких каталогов, FIFO и так далее), используйте найти -type f , чтобы ограничить то, что возвращено.

35
ответ дан 28 November 2019 в 00:51
поделиться

Я считаю, что

ls | sort -f | uniq -i -d

проще, быстрее, и даст тот же результат

6
ответ дан 28 November 2019 в 00:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: