Procura por nomes de arquivos duplicados dentro da hierarquia de pastas?

22

Eu tenho uma pasta chamada img , essa pasta tem muitos níveis de subpastas, todos contendo imagens. Vou importá-los para um servidor de imagens.

Normalmente, as imagens (ou quaisquer arquivos) podem ter o mesmo nome, desde que estejam em um caminho de diretório diferente ou tenham uma extensão diferente. No entanto, o servidor de imagem para o qual estou importando exige que todos os nomes de imagens sejam exclusivos (mesmo que as extensões sejam diferentes).

Por exemplo, as imagens background.png e background.gif não seriam permitidas porque, apesar de terem extensões diferentes, ainda têm o mesmo nome de arquivo. Mesmo se eles estiverem em subpastas separadas, eles ainda precisam ser únicos.

Estou pensando se posso fazer uma pesquisa recursiva na pasta img para encontrar uma lista de arquivos com o mesmo nome (excluindo a extensão).

Existe um comando que pode fazer isso?

    
por JD Isaacks 13.06.2011 / 17:28

6 respostas

15

FSlint éumlocalizadorduplicadoversátilqueincluiumafunçãoparaencontrarnomesduplicados:

O pacote FSlint para Ubuntu enfatiza a interface gráfica, mas como explicado na FAQ do FSlint A interface da linha de comandos está disponível através dos programas em /usr/share/fslint/fslint/ . Use a opção --help para documentação, por exemplo:

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

Exemplo de uso:

$ /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
    
por ændrük 13.06.2011 / 21:02
26
find . -mindepth 1 -printf '%h %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | tr ' ' '/'

Como o comentário afirma, isso também encontrará pastas. Aqui está o comando para restringir a arquivos:

find . -mindepth 1 -type f -printf '%p %f\n' | ...
    
por ojblass 13.06.2011 / 22:57
5

Salve isso em um arquivo chamado 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

Em seguida, torne o arquivo executável:

chmod +x duplicates.py

Executar em, e. assim:

./duplicates.py ~/images

Ele deve gerar pares de arquivos que tenham o mesmo nome de base (1). Escrito em python, você deve ser capaz de modificá-lo.

    
por loevborg 13.06.2011 / 23:01
3

Suponho que você só precisa ver essas "duplicatas" e manipulá-las manualmente. Se assim for, este código bash4 deve fazer o que você quer eu acho.

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

Consulte link e / ou o manual bash para obter ajuda sobre a sintaxe de matriz associativa.

    
por geirha 13.06.2011 / 20:23
1

Isso é 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"

Torne-o executável:

chmod a+x bname 

Invoque:

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

Pro:

  • É simples e simples, portanto, extensível.
  • Manipula espaços em branco, tabulações, quebras de linha e pagefeeds em nomes de arquivos, afaik. (Assumindo que não existe no nome da extensão).

Con:

  • Ele encontra sempre o arquivo em si, e se ele encontrar um.gif para a.jpg, ele também encontrará a.jpg para a.gif. Portanto, para 10 arquivos do mesmo nome de base, ele encontra 100 correspondências no final.
por user unknown 13.06.2011 / 22:15
0

Melhoria no script do loevborg, para minhas necessidades (inclui saída agrupada, lista negra, saída mais limpa durante a varredura). Eu estava digitalizando uma unidade de 10TB, então eu precisava de uma saída um pouco mais limpa.

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)
    
por skoczen 16.09.2018 / 05:36