Yanıtlar:
Kullanılabilir GNU yardımcı programlarınız varsa (veya en azından sıfır sonlu satırlarla başa çıkabilecek bir küme), başka bir yanıtın harika bir yöntemi vardır:
find . -maxdepth 1 -print0 | sort -z | uniq -diz
Not: çıkışın sıfır sonlu dizeleri olacaktır; ileride işlemek için kullandığınız araç bunu kaldırabilmelidir.
Sıfır sonlu satırlarla ilgilenen araçların yokluğunda veya kodunuzun bu tür araçların bulunmadığı ortamlarda çalıştığından emin olmak istiyorsanız, küçük bir komut dosyasına ihtiyacınız vardır:
#!/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
Bu delilik nedir? Bunu çılgın dosya adları için güvenli hale getiren tekniklerin açıklaması için bu cevaba bakınız .
-mindepth
'Lere gerçekten ihtiyacınız var mı?
find
; Cevabı GNU olmayan bir çözüm içerecek şekilde düzenledim.
Yukarıda birçok karmaşık cevap var, bu hepsinden daha basit ve daha hızlı görünüyor:
find . -maxdepth 1 | sort -f | uniq -di
Alt dizinlerde yinelenen dosya adları bulmak istiyorsanız, tüm yolu değil, yalnızca dosya adını karşılaştırmanız gerekir:
find . -maxdepth 2 -printf "%f\n" | sort -f | uniq -di
Edit: Shawn J. Goff yeni satır karakterleri ile dosya adlarınız varsa, bu başarısız olacağını belirtti. GNU yardımcı programlarını kullanıyorsanız, bunları da çalıştırabilirsiniz:
find . -maxdepth 1 -print0 | sort -fz | uniq -diz
-print0
(Bulma işlemi için) ve -z
yeni satır dizeleri sonlandırıldı yerine, seçenek bunlar neden boş karakter sonlandırmalı dizgeler üzerinde çalışmaya (tür ve uniq). Dosya adları NUL içeremediğinden, bu tüm dosya adları için geçerlidir.
Dosya adları listesini büyük / küçük harfe duyarlı olmayan bir şekilde sıralayın ve kopyaları yazdırın. sort
büyük / küçük harfe duyarlı olmayan sıralama seçeneği vardır. GNU da öyle uniq
, ancak diğer uygulamalar değil ve yapabileceğiniz tek şey, uniq
karşılaşılan ilk şey hariç her öğeyi bir kopya halinde yazdırmak. GNU araçlarıyla, hiçbir dosya adının yeni satır içermediğini varsayarsak, her yinelenen kümede bir tane olmak üzere tüm öğeleri yazdırmanın kolay bir yolu vardır:
for x in *; do printf "%s\n" "$x"; done |
sort -f |
uniq -id
Taşınabilir olarak, hiçbir dosya adının yeni satır içermediğini varsayarak, her yinelenen kümedeki tüm öğeleri yazdırmak için:
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 }'
Yeni satırlar içeren dosya adlarını barındırmanız gerekiyorsa Perl veya Python'a gidin. Aşağıdaki örnek kod, kendi çıktısında adları ayırmak için yeni satırlar kullandığından, çıktıyı düzeltmeniz veya aynı dilde daha fazla işlem gerçekleştirmeniz gerekebilir.
perl -e '
foreach (glob("*")) {push @{$f{lc($_)}}, $_}
foreach (keys %f) {@names = @{$f{$_}}; if (@names > 1) {print "$_\n" foreach @names}}
'
İşte saf bir zsh çözümü. Yinelenen öğeleri bir dizi veya glob sonucunda tutmanın yerleşik bir yolu olmadığından, biraz ayrıntılıdır.
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 olmadan find
:
LANG=en_US ls | tr '[A-Z]' '[a-z]' | uniq -c | awk '$1 >= 2 {print $2}'
tr
olduğu çok karakterin başına tek bayt daha kullanan herhangi bir karakter setinde wreak tahribat ihtimali. UTF-8'in sadece ilk 256 karakteri kullanıldığında güvenlidir tr
. Gönderen Vikipedi tr (Unix) .. Çoğu sürümleri tr
GNU dahil, tr
ve klasik Unix tr
, TEK BAYT'lardan ameliyat ve Unicode uyumlu olmayan ..
uniq
, büyük / küçük harf duyarsız bir bayrağa sahiptir i.
Sonunda şu şekilde başardım:
find . | tr '[:upper:]' '[:lower:]' | sort | uniq -d
Ben tam yol (alt dizinler bir sürü) dahil neden find
yerine kullandım ls
. Bunu nasıl yapacağımı bulamadım ls
.
sort
ve uniq
sırasıyla görmezden durum bayrakları, f ve i var.
Dosyalardan birini vb. Yeniden adlandırmak isteyen herkes için:
find . -maxdepth 1 | sort -f | uniq -di | while read f; do echo mv "$f" "${f/.txt/_.txt}"; done