ifelse
векторизован, поэтому, если я правильно понимаю ваш код, вам это не нужно sapply
. И я бы не использовал слияние - я бы использовал SQLite или PostgreSQL.
Некоторые примеры данных тоже помогли бы: -)
Другой ответ велик, но вместо «довольно чудовищного» сценария 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";
}
}
Попробуйте:
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
, чтобы ограничить то, что возвращено.
Я считаю, что
ls | sort -f | uniq -i -d
проще, быстрее, и даст тот же результат