Mencari nama file duplikat dalam hierarki folder?

29

Saya memiliki folder bernama img, folder ini memiliki banyak tingkatan sub-folder, yang semuanya berisi gambar. Saya akan mengimpornya ke server gambar.

Biasanya gambar (atau file apa saja) dapat memiliki nama yang sama selama mereka berada di jalur direktori yang berbeda atau memiliki ekstensi yang berbeda. Namun, server gambar tempat saya mengimpornya memerlukan semua nama gambar untuk menjadi unik (bahkan jika ekstensi berbeda).

Misalnya gambar background.pngdan background.giftidak akan diizinkan karena meskipun mereka memiliki ekstensi yang berbeda mereka masih memiliki nama file yang sama. Bahkan jika mereka berada di sub-folder yang terpisah, mereka masih harus unik.

Jadi saya bertanya-tanya apakah saya dapat melakukan pencarian berulang di imgfolder untuk menemukan daftar file yang memiliki nama yang sama (tidak termasuk ekstensi).

Apakah ada perintah yang bisa melakukan ini?

JD Isaacks
sumber
@ DavidFoerster Anda benar! Saya tidak tahu mengapa saya berpikir ini mungkin duplikat dari Bagaimana menemukan (dan menghapus) file duplikat , tetapi jelas itu bukan.
Eliah Kagan

Jawaban:

17

FSlint Instal fslint adalah pengganda duplikat serbaguna yang mencakup fungsi untuk menemukan nama duplikat:

FSlint

Paket FSlint untuk Ubuntu menekankan antarmuka grafis, tetapi seperti yang dijelaskan dalam FAQ FSlint, antarmuka baris perintah tersedia melalui program-program di /usr/share/fslint/fslint/. Gunakan --helpopsi untuk dokumentasi, misalnya:

$ /usr/share/fslint/fslint/fslint --help
File system lint.
A collection of utilities to find lint on a filesystem.
To get more info on each utility run 'util --help'.

findup -- find DUPlicate files
findnl -- find Name Lint (problems with filenames)
findu8 -- find filenames with invalid utf8 encoding
findbl -- find Bad Links (various problems with symlinks)
findsn -- find Same Name (problems with clashing names)
finded -- find Empty Directories
findid -- find files with dead user IDs
findns -- find Non Stripped executables
findrs -- find Redundant Whitespace in files
findtf -- find Temporary Files
findul -- find possibly Unused Libraries
zipdir -- Reclaim wasted space in ext2 directory entries
$ /usr/share/fslint/fslint/findsn --help
find (files) with duplicate or conflicting names.
Usage: findsn [-A -c -C] [[-r] [-f] paths(s) ...]

If no arguments are supplied the $PATH is searched for any redundant
or conflicting files.

-A reports all aliases (soft and hard links) to files.
If no path(s) specified then the $PATH is searched.

If only path(s) specified then they are checked for duplicate named
files. You can qualify this with -C to ignore case in this search.
Qualifying with -c is more restictive as only files (or directories)
in the same directory whose names differ only in case are reported.
I.E. -c will flag files & directories that will conflict if transfered
to a case insensitive file system. Note if -c or -C specified and
no path(s) specifed the current directory is assumed.

Contoh penggunaan:

$ /usr/share/fslint/fslint/findsn /usr/share/icons/ > icons-with-duplicate-names.txt
$ head icons-with-duplicate-names.txt 
-rw-r--r-- 1 root root    683 2011-04-15 10:31 Humanity-Dark/AUTHORS
-rw-r--r-- 1 root root    683 2011-04-15 10:31 Humanity/AUTHORS
-rw-r--r-- 1 root root  17992 2011-04-15 10:31 Humanity-Dark/COPYING
-rw-r--r-- 1 root root  17992 2011-04-15 10:31 Humanity/COPYING
-rw-r--r-- 1 root root   4776 2011-03-29 08:57 Faenza/apps/16/DC++.xpm
-rw-r--r-- 1 root root   3816 2011-03-29 08:57 Faenza/apps/22/DC++.xpm
-rw-r--r-- 1 root root   4008 2011-03-29 08:57 Faenza/apps/24/DC++.xpm
-rw-r--r-- 1 root root   4456 2011-03-29 08:57 Faenza/apps/32/DC++.xpm
-rw-r--r-- 1 root root   7336 2011-03-29 08:57 Faenza/apps/48/DC++.xpm
-rw-r--r-- 1 root root    918 2011-03-29 09:03 Faenza/apps/16/Thunar.png
ændrük
sumber
Terima kasih, ini berhasil. Beberapa hasilnya berwarna ungu dan sebagian berwarna hijau. Apakah Anda tahu apa arti perbedaan warna?
JD Isaacks
@ John Sepertinya FSlint menggunakan ls -luntuk memformat outputnya. Pertanyaan ini harus menjelaskan apa arti warna.
ændrük
FSlint memiliki banyak dependensi.
Navin
31
find . -mindepth 1 -printf '%h %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | tr ' ' '/'

Sebagai komentar menyatakan, ini akan menemukan folder juga. Ini adalah perintah untuk membatasi file:

find . -mindepth 1 -type f -printf '%p %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | cut -d' ' -f1
ojblass
sumber
Saya mengubah solusi sehingga mengembalikan path (relatif) penuh dari semua duplikat. Sayangnya itu mengasumsikan bahwa nama jalur tidak mengandung spasi putih karena uniqtidak menyediakan fitur untuk memilih pembatas bidang yang berbeda.
David Foerster
@ DavidvidFoerster, rev 6 Anda adalah perbaikan, tetapi mengenai komentar Anda di sana, sejak kapan sedusang? Batin? Yakin. Usang? Bukannya aku sadar. (Dan saya baru saja mencari untuk memeriksa.)
cp.engr
@ cp.engr: sed tidak usang. Doa itu menjadi usang setelah perubahan saya yang lain.
David Foerster
@ DavidFoerster, usang sepertinya bukan kata yang tepat bagi saya. Saya pikir "dihindarkan" akan lebih cocok. Apapun, terima kasih telah menjelaskan.
cp.engr
@ cp.engr: Terima kasih atas sarannya! Saya tidak tahu kata itu tetapi tampaknya lebih cocok dengan situasinya.
David Foerster
8

Simpan ini ke file bernama duplicates.py

#!/usr/bin/env python

# Syntax: duplicates.py DIRECTORY

import os, sys

top = sys.argv[1]
d = {}

for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        fn = os.path.join(root, name)
        basename, extension = os.path.splitext(name)

        basename = basename.lower() # ignore case

        if basename in d:
            print(d[basename])
            print(fn)
        else:
            d[basename] = fn

Kemudian buat file tersebut dapat dieksekusi:

chmod +x duplicates.py

Jalankan di misalnya seperti ini:

./duplicates.py ~/images

Seharusnya output pasangan file yang memiliki nama sama (1). Ditulis dengan python, Anda harus dapat memodifikasinya.

loevborg
sumber
Tampaknya tidak berfungsi dengan baik. Mendeteksi P001.ORFdan P001 (1).ORFsebagai duplikat dan juga sepertinya berpikir bahwa 60% dari file saya adalah duplikat yang salah saya cukup yakin. fslintmenemukan sejumlah nama file duplikat yang mendekati 3%.
Rolf
3

Saya berasumsi Anda hanya perlu melihat "duplikat" ini, lalu menanganinya secara manual. Jika demikian, kode bash4 ini harus melakukan apa yang Anda inginkan.

declare -A array=() dupes=()
while IFS= read -r -d '' file; do 
    base=${file##*/} base=${base%.*}
    if [[ ${array[$base]} ]]; then 
        dupes[$base]+=" $file"
    else
        array[$base]=$file
    fi
done < <(find /the/dir -type f -print0)

for key in "${!dupes[@]}"; do 
    echo "$key: ${array[$key]}${dupes[$key]}"
done

Lihat http://mywiki.wooledge.org/BashGuide/Arrays#Associative_Arrays dan / atau manual bash untuk bantuan tentang sintaks array asosiatif.

geirha
sumber
Bagaimana saya menjalankan perintah seperti itu di terminal? Apakah ini sesuatu yang saya perlu simpan ke file terlebih dahulu dan jalankan file?
JD Isaacks
@John Isaacks Anda dapat menyalin / menempelkannya ke terminal atau Anda dapat memasukkannya ke dalam file dan menjalankannya sebagai skrip. Kasus mana pun akan mencapai hal yang sama.
geirha
1

Ini adalah bname:

#!/bin/bash
#
#  find for jpg/png/gif more files of same basename 
#
# echo "processing ($1) $2"
bname=$(basename "$1" .$2)
find -name "$bname.jpg" -or -name "$bname.png"

Jadikan itu dapat dieksekusi:

chmod a+x bname 

Tanyakan itu:

for ext in jpg png jpeg gif tiff; do find -name "*.$ext" -exec ./bname "{}" $ext ";"  ; done

Pro:

  • Sangat mudah dan sederhana, oleh karena itu dapat diperpanjang.
  • Menangani blank, tab, linebreak dan pagefeed dalam nama file, afaik. (Dengan asumsi tidak ada yang namanya dalam ekstensi-nama).

Menipu:

  • Ia menemukan selalu file itu sendiri, dan jika ia menemukan a.gif untuk a.jpg, ia akan menemukan a.jpg untuk a.gif juga. Jadi untuk 10 file dengan nama yang sama, pada akhirnya menemukan 100 kecocokan.
Pengguna tidak diketahui
sumber
0

Perbaikan skrip loevborg, untuk kebutuhan saya (termasuk keluaran yang dikelompokkan, daftar hitam, keluaran yang lebih bersih saat memindai). Saya memindai drive 10TB, jadi saya membutuhkan output yang sedikit lebih bersih.

Pemakaian:

python duplicates.py DIRNAME

duplicates.py

    #!/usr/bin/env python

    # Syntax: duplicates.py DIRECTORY

    import os
    import sys

    top = sys.argv[1]
    d = {}

    file_count = 0

    BLACKLIST = [".DS_Store", ]

    for root, dirs, files in os.walk(top, topdown=False):
        for name in files:
            file_count += 1
            fn = os.path.join(root, name)
            basename, extension = os.path.splitext(name)

            # Enable this if you want to ignore case.
            # basename = basename.lower()

            if basename not in BLACKLIST:
                sys.stdout.write(
                    "Scanning... %s files scanned.  Currently looking at ...%s/\r" %
                    (file_count, root[-50:])
                )

                if basename in d:
                    d[basename].append(fn)
                else:
                    d[basename] = [fn, ]

    print("\nDone scanning. Here are the duplicates found: ")

    for k, v in d.items():
        if len(v) > 1:
            print("%s (%s):" % (k, len(v)))
            for f in v:
                print (f)
skoczen
sumber