Jawaban:
Jika Anda memiliki utilitas GNU (atau setidaknya satu set yang dapat menangani baris tanpa-penghentian), jawaban lain memiliki metode yang hebat:
find . -maxdepth 1 -print0 | sort -z | uniq -diz
Catatan: output akan memiliki string yang diakhiri nol; alat yang Anda gunakan untuk proses selanjutnya harus bisa mengatasinya.
Dengan tidak adanya alat yang berurusan dengan garis nol-putus, atau jika Anda ingin memastikan kode Anda bekerja di lingkungan di mana alat tersebut tidak tersedia, Anda memerlukan skrip kecil:
#!/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
Gila apa ini? Lihat jawaban ini untuk penjelasan tentang teknik yang membuat ini aman untuk nama file gila.
-mindepth
?
find
; Saya telah mengedit jawaban untuk menyertakan solusi non-GNU.
Ada banyak jawaban rumit di atas, ini tampaknya lebih sederhana dan lebih cepat daripada semuanya:
find . -maxdepth 1 | sort -f | uniq -di
Jika Anda ingin menemukan nama file duplikat di subdirektori maka Anda hanya perlu membandingkan nama file, bukan keseluruhan path:
find . -maxdepth 2 -printf "%f\n" | sort -f | uniq -di
Sunting: Shawn J. Goff telah menunjukkan bahwa ini akan gagal jika Anda memiliki nama file dengan karakter baris baru. Jika Anda menggunakan utilitas GNU, Anda dapat membuatnya bekerja juga:
find . -maxdepth 1 -print0 | sort -fz | uniq -diz
Opsi -print0
(untuk menemukan) dan -z
(untuk mengurutkan dan uniq) menyebabkan mereka bekerja pada string yang diakhiri NUL, alih-alih string yang diakhiri baris baru. Karena nama file tidak dapat berisi NUL, ini berfungsi untuk semua nama file.
Urutkan daftar nama file dengan cara case-sensitive dan cetak duplikat. sort
memiliki opsi untuk penyortiran case-insensitive. Begitu juga GNU uniq
, tetapi bukan implementasi lain, dan yang dapat Anda lakukan uniq
hanyalah mencetak setiap elemen dalam satu set duplikat kecuali yang pertama kali ditemukan. Dengan alat GNU, dengan asumsi bahwa tidak ada nama file berisi baris baru, ada cara mudah untuk mencetak semua elemen kecuali satu di setiap set duplikat:
for x in *; do printf "%s\n" "$x"; done |
sort -f |
uniq -id
Portable, untuk mencetak semua elemen dalam setiap set duplikat, dengan asumsi bahwa tidak ada nama file yang mengandung baris baru:
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 }'
Jika Anda perlu mengakomodasi nama file yang berisi baris baru, pilih Perl atau Python. Perhatikan bahwa Anda mungkin perlu mengubah output, atau lebih baik melakukan pemrosesan lebih lanjut dalam bahasa yang sama, karena kode sampel di bawah ini menggunakan baris baru untuk memisahkan nama dalam outputnya sendiri.
perl -e '
foreach (glob("*")) {push @{$f{lc($_)}}, $_}
foreach (keys %f) {@names = @{$f{$_}}; if (@names > 1) {print "$_\n" foreach @names}}
'
Inilah solusi zsh murni. Ini agak bertele-tele, karena tidak ada cara bawaan untuk menyimpan elemen duplikat dalam array atau hasil glob.
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
Tanpa GNU find
:
LANG=en_US ls | tr '[A-Z]' '[a-z]' | uniq -c | awk '$1 >= 2 {print $2}'
tr
adalah sangat mungkin untuk melampiaskan malapetaka di setiap set karakter yang menggunakan lebih dari satu byte per karakter. Hanya 256 karakter pertama dari UTF-8 yang aman saat digunakan tr
. Dari Wikipedia tr (Unix) .. Sebagian besar versi tr
, termasuk GNU tr
dan Unix klasik tr
, beroperasi pada SINGLE BYTES dan tidak sesuai dengan Unicode ..
uniq
memiliki flag case-insensitive i.
Saya akhirnya berhasil seperti ini:
find . | tr '[:upper:]' '[:lower:]' | sort | uniq -d
Saya menggunakan find
alih-alih ls
karena saya membutuhkan path lengkap (banyak subdirektori) yang disertakan. Saya tidak menemukan cara melakukan ini ls
.
sort
dan masing-masing uniq
memiliki flag abaikan, f dan i.
Untuk siapa pun yang ingin mengubah nama, dll, salah satu file:
find . -maxdepth 1 | sort -f | uniq -di | while read f; do echo mv "$f" "${f/.txt/_.txt}"; done