Localizando arquivos duplicados por nome ignorando o caso em subdiretórios

3

Como é possível listar nomes de arquivos duplicados em um sistema Linux

  • ignorando o caso
  • incluindo todos os subdiretórios

Os arquivos não devem ser comparados pelo seu conteúdo , mas apenas pelos seus nomes . A saída deve ser uma lista de nomes de arquivos, incluindo o caminho, para que seja possível executar mais comandos nesses arquivos.

Vamos supor que temos

ls -1R /tmp/
foo
BAR
barfoo
a/BAr
a/b/bar
c/bAr

A saída do script / find do filtro deve ser

/tmp/BAR
/tmp/a/BAr
/tmp/a/b/bar
/tmp/c/bAr
    
por Jonas Stein 31.10.2014 / 17:29

2 respostas

3

find . -printf "%p %f\n" | sort -f -k2 | uniq -Di -f1

Especifique sua opção de iniciar o diretório para find se você não quiser começar em . . Adicione -type f se você quiser apenas nomes de arquivo .

  • O comando find produz uma lista de nomes de arquivos (e diretórios), em ordem de diretórios (ou seja, ordem aleatória, até onde você sabe).
  • -printf "%p %f\n" imprime o nome do caminho completo (relativo a . ) e o nome do arquivo.
  • sort -f é a abreviação de sort --ignore-case , ou seja, classifica a lista de nomes de arquivos de uma maneira que não diferencia maiúsculas e minúsculas
  • -k2 diz para usar o segundo campo como a chave de classificação.
  • uniq -Di -f1 é a abreviação de uniq --all-repeated --ignore-case --skip-fields=1 , isto é, mostra (todas) as linhas de saída de find que ocorrem repetidamente, com base na comparação de maiúsculas e minúsculas do segundo campo e além (ou seja, que têm o mesmo -insensível) nome do arquivo).

Isso deve dar a saída que você deseja, exceto que cada linha terá o nome do arquivo repetido no final. Se você quiser se livrar disso, canalize para sed 's/ .*//' .

Algumas dicas:

  • Se você tiver diretórios cujos nomes são os mesmos, exceto caso, e eles contêm arquivos cujos nomes são os mesmos, exceto caso, por exemplo,

    documents/design.doc
    Documents/Design.doc
    

    eles serão listados.

  • Se você tiver arquivos (ou diretórios) cujos nomes contenham espaços, tabulações ou novas linhas, isso será interrompido.

por 31.10.2014 / 17:46
2

Isso funciona para nomes de arquivo básicos, mas não funcionará para arquivos com retornos de carro e, provavelmente, alguns outros casos de borda.

FilesNoPath=$(find . -printf "%f\n")
FilesWithPath=$(find .)

oldIFS=$IFS
IFS=$'\n'
for filename in $FilesNoPath;
do
    Matches=$(echo "$FilesWithPath" | grep -i "/$filename$")
    if [ $(echo "$Matches" | wc -l) -gt 1 ]
    then
        echo Found matches:
        echo "$Matches"
        FilesWithPath=$(echo "$FilesWithPath" | grep -vi "/$filename$")
    fi
done
IFS=$oldIFS

Você pode substituir o . nos dois comandos find com /path/to/your/files se quiser que a saída mostre o caminho completo e / ou não queira executá-lo a partir do diretório pai dos arquivos correspondentes.

    
por 31.10.2014 / 18:16