Відповіді:
Якщо у вас є утиліти 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
's?
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
має можливість сортування, що не враховує регістр. Так само і GNU uniq
, але не інші реалізації, і все, що ви можете зробити, 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
. З Вікіпедії 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