Cerca nomi di file duplicati nella gerarchia di cartelle?


29

Ho una cartella chiamata img, questa cartella ha molti livelli di sottocartelle, tutte contenenti immagini. Ho intenzione di importarli in un server di immagini.

Normalmente le immagini (o qualsiasi file) possono avere lo stesso nome purché si trovino in un percorso di directory diverso o abbiano un'estensione diversa. Tuttavia, il server di immagini in cui li sto importando richiede che tutti i nomi delle immagini siano univoci (anche se le estensioni sono diverse).

Ad esempio le immagini background.pnge background.gifnon sarebbero consentite perché anche se hanno estensioni diverse hanno sempre lo stesso nome file. Anche se si trovano in sottocartelle separate, devono comunque essere univoci.

Quindi mi chiedo se posso fare una ricerca ricorsiva nella imgcartella per trovare un elenco di file con lo stesso nome (esclusa l'estensione).

C'è un comando che può fare questo?


@DavidFoerster Hai ragione! Non ho idea del perché avessi pensato che questo potesse essere un duplicato di Come trovare (ed eliminare) i file duplicati , ma chiaramente non lo è.
Eliah Kagan,

Risposte:


17

FSlint Installa fslint è un versatile cercatore di duplicati che include una funzione per trovare nomi duplicati:

FSlint

Il pacchetto FSlint per Ubuntu enfatizza l'interfaccia grafica, ma come è spiegato in FAQ di FSlint è disponibile un'interfaccia da riga di comando tramite i programmi in /usr/share/fslint/fslint/. Utilizzare l' --helpopzione per la documentazione, ad esempio:

$ /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.

Esempio di utilizzo:

$ /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

Grazie ha funzionato. Alcuni dei risultati sono in viola e altri in verde. Sai fuori mano cosa significano i diversi colori?
JD Isaacks,

@ John Sembra che FSlint stia usando ls -lper formattare il suo output. Questa domanda dovrebbe spiegare cosa significano i colori.
ændrük,

FSlint ha molte dipendenze.
Navin,

31
find . -mindepth 1 -printf '%h %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | tr ' ' '/'

Come afferma il commento, questo troverà anche le cartelle. Ecco il comando per limitarlo ai file:

find . -mindepth 1 -type f -printf '%p %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | cut -d' ' -f1

Ho modificato la soluzione in modo che restituisca il percorso completo (relativo) di tutti i duplicati. Sfortunatamente si presume che i nomi dei percorsi non contengano spazi bianchi perché uniqnon forniscono una funzione per selezionare un delimitatore di campo diverso.
David Foerster,

@DavidFoerster, il tuo rev 6 è stato un miglioramento, ma per quanto riguarda il tuo commento lì, da quando è sedobsoleto? Arcano? Sicuro. Obsoleto? Non che ne sia consapevole. (E ho appena cercato di controllare.)
cp.engr

@ cp.engr: sed non è obsoleto. La sua invocazione è diventata obsoleta dopo un altro mio cambio.
David Foerster,

@DavidFoerster, allora obsoleto non mi sembra la parola giusta. Penso che "ovviato" sarebbe una soluzione migliore. Indipendentemente da ciò, grazie per il chiarimento.
cp.engr

@ cp.engr: grazie per il suggerimento! Non sapevo quella parola ma sembra adattarsi meglio alla situazione.
David Foerster,

8

Salvalo in un file chiamato 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

Quindi rendere eseguibile il file:

chmod +x duplicates.py

Esegui ad esempio in questo modo:

./duplicates.py ~/images

Dovrebbe generare coppie di file con lo stesso nome di base (1). Scritto in Python, dovresti essere in grado di modificarlo.


Non sembra funzionare correttamente. Rileva P001.ORFe P001 (1).ORFcome duplicati e inoltre sembra pensare che il 60% dei miei file sia duplicato, il che è sbagliato, ne sono abbastanza sicuro. fslinttrovato un numero realistico di nomi file duplicati che si avvicina al 3%.
Rolf,

3

Presumo che tu debba solo vedere questi "duplicati", quindi gestirli manualmente. Se è così, questo codice bash4 dovrebbe fare quello che vuoi, penso.

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

Vedere http://mywiki.wooledge.org/BashGuide/Arrays#Associative_Arrays e / o il manuale di bash per assistenza sulla sintassi dell'array associativo.


Come eseguo un comando simile in un terminale? È qualcosa che devo prima salvare in un file ed eseguire il file?
JD Isaacks,

@John Isaacks Puoi copiarlo / incollarlo nel terminale oppure puoi inserirlo in un file ed eseguirlo come script. Entrambi i casi raggiungeranno lo stesso.
geirha,

1

Questo è 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"

Renderlo eseguibile:

chmod a+x bname 

Invocalo:

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

Pro:

  • È diretto e semplice, quindi estensibile.
  • Gestisce spazi vuoti, schede, interruzioni di riga e avanzamenti di pagina nei nomi di file, afaik. (Supponendo che nulla di simile nel nome dell'estensione).

con:

  • Trova sempre il file stesso e se trova a.gif per a.jpg, troverà anche a.jpg per a.gif. Quindi, per 10 file con lo stesso nome di base, trova 100 corrispondenze alla fine.

0

Miglioramento della sceneggiatura di Loevborg, per le mie esigenze (include output raggruppato, lista nera, output più pulito durante la scansione). Stavo scannerizzando un'unità da 10 TB, quindi avevo bisogno di un output un po 'più pulito.

Uso:

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.