Ответы:
Если у вас есть утилиты GNU (или, по крайней мере, набор, который может работать с нулевыми концами), у другого ответа есть отличный метод:
find . -maxdepth 1 -print0 | sort -z | uniq -diz
Примечание: вывод будет иметь строки с нулевым символом в конце; инструмент, который вы используете для дальнейшей обработки, он должен быть в состоянии справиться с этим.
В отсутствие инструментов, которые работают с нулевыми концами строк, или если вы хотите убедиться, что ваш код работает в средах, где такие инструменты недоступны, вам нужен небольшой скрипт:
#!/bin/sh
for f in *; do
find . -maxdepth 1 -iname ./"$f" -exec echo \; | wc -l | while read count; do
[ $count -gt 1 ] && echo $f
done
done
Что это за безумие? Посмотрите этот ответ для объяснения методов, которые делают это безопасным для сумасшедших имен файлов.
-mindepth
?
find
; Я отредактировал ответ, чтобы включить решение без GNU.
Выше приведено много сложных ответов, которые кажутся проще и быстрее, чем все:
find . -maxdepth 1 | sort -f | uniq -di
Если вы хотите найти повторяющиеся имена файлов в подкаталогах, вам нужно сравнить только имя файла, а не весь путь:
find . -maxdepth 2 -printf "%f\n" | sort -f | uniq -di
Изменить: Шон Дж. Гофф указал, что это не удастся, если у вас есть имена файлов с символами новой строки. Если вы используете утилиты GNU, вы также можете заставить их работать:
find . -maxdepth 1 -print0 | sort -fz | uniq -diz
-print0
(Для находки) и -z
вариант (для сортировки и Uniq) может привести к их работе на NUL-терминированые строки, вместо новой строки завершаются строки. Поскольку имена файлов не могут содержать NUL, это работает для всех имен файлов.
Сортируйте список имен файлов без учета регистра и печатайте дубликаты. sort
имеет возможность сортировки без учета регистра. То же uniq
самое делает GNU , но не другие реализации, и все, что вы можете сделать, uniq
это напечатать каждый элемент в наборе дубликатов, кроме первого, с которым вы столкнулись. С инструментами GNU, при условии, что ни одно имя файла не содержит новой строки, есть простой способ напечатать все элементы, кроме одного в каждом наборе дубликатов:
for x in *; do printf "%s\n" "$x"; done |
sort -f |
uniq -id
В частности, для печати всех элементов в каждом наборе дубликатов, при условии, что ни одно имя файла не содержит символ новой строки:
for x in *; do printf "%s\n" "$x"; done |
sort -f |
awk '
tolower($0) == tolower(prev) {
print prev;
while (tolower($0) == tolower(prev)) {print; getline}
}
1 { prev = $0 }'
Если вам нужно разместить имена файлов, содержащие переводы строк, выберите Perl или Python. Обратите внимание, что вам может потребоваться настроить вывод или лучше выполнить дальнейшую обработку на том же языке, так как в приведенном ниже примере кода используются новые строки для разделения имен в собственном выводе.
perl -e '
foreach (glob("*")) {push @{$f{lc($_)}}, $_}
foreach (keys %f) {@names = @{$f{$_}}; if (@names > 1) {print "$_\n" foreach @names}}
'
Вот чистое решение Zsh. Это немного многословно, поскольку нет встроенного способа сохранить дублирующиеся элементы в массиве или глобальном результате.
a=(*)(N); a=("${(@io)a}")
[[ $#a -le 1 ]] ||
for i in {2..$#a}; do
if [[ ${(L)a[$i]} == ${(L)a[$((i-1))]} ]]; then
[[ ${(L)a[$i-2]} == ${(L)a[$((i-1))]} ]] || print -r $a[$((i-1))]
print -r $a[$i]
fi
done
Без GNU find
:
LANG=en_US ls | tr '[A-Z]' '[a-z]' | uniq -c | awk '$1 >= 2 {print $2}'
tr
является очень вероятно , чтобы посеять хаос на любой набор символов , который использует более одного байта на символ. Только первые 256 символов UTF-8 безопасны при использовании tr
. Из Википедии (Unix) . Большинство версий tr
, включая GNU tr
и классический Unix tr
, работают на ОДНОБАЙТОВ и не совместимы с Юникодом.
uniq
имеет флаг без учета регистра i.
Наконец-то мне это удалось:
find . | tr '[:upper:]' '[:lower:]' | sort | uniq -d
Я использовал find
вместо того, чтобы ls
мне нужен был полный путь (много подкаталогов). Я не нашел, как это сделать ls
.
sort
и uniq
имеют флажки игнорирования, f и i соответственно.
Для тех, кто хочет затем переименовать и т. Д. Один из файлов:
find . -maxdepth 1 | sort -f | uniq -di | while read f; do echo mv "$f" "${f/.txt/_.txt}"; done