Para listar nomes de arquivos duplicados em uma listagem?

1
bash-3.00$ cat f.txt
-rw-r--r--   1 mukesh   other        102 Nov  5 18:32 f1.txt
-rw-r--r--   1 mukesh   other         19 Nov  5 18:32 f2.txt
-rw-r--r--   1 mukesh   other        204 Nov  5 18:32 f3.txt //DUPLICATE
-rw-r--r--   1 mukesh   other        204 Nov  6 18:32 f3.txt  //DUPLICATE
-rw-r--r--   1 mukesh   other        204 Nov  6 18:32 f100.txt

Digamos que eu tenha os nomes de arquivo listados em um arquivo chamado f.txt. Eu quero listar todos os nomes de arquivos que possuem uma duplicata ( somente file-name ), exibir o nome do arquivo duplicado e o número de duplicatas.

Por exemplo: Na lista acima, f3.txt tem uma duplicata e há um total de 2 nomes de arquivo f3.txt encontrados.

    
por munish 06.11.2011 / 14:53

3 respostas

2

Como você mencionou awk , aqui está uma solução:

awk '{d[$9]++}END{for(f in d)if(d[f]>1)print d[f],f}' f.txt

Se você também tiver arquivos com caracteres de espaço em seus nomes, será necessária alguma solução alternativa:

awk '{f=$9;for(i=10;i<=NF;i++)f=f" "$i;d[f]++}END{for(f in d)if(d[f]>1)print d[f],f}' f.txt

Observe que a solução alternativa acima pode falhar, por exemplo, ao lidar com links simbólicos. Afinal, analisar ls output não é uma boa ideia. Seria melhor gerar seu f.txt de alguma outra forma, se possível. (Por exemplo, find ou stat , onde você tem melhor controle sobre o formato da lista.)

    
por 06.11.2011 / 15:59
1

Aqui está uma solução em bash puro, pois sua pergunta indica claramente que você tem o bash 3 disponível:

#!/bin/bash

if [[ -t 0 ]]; then
    printf '%s\n' 'No input!'
    exit 1
fi

while read -ra _file; do
    _file="${foo[*]:8}"

    for _file_name_already_known in "${_files[@]}"; do
        if [[ ${_file_name_already_known} == "${_file}" ]]; then
            for _file_name_already_printed in "${_already_printed[@]}"; do
                [[ ${_file_name_already_printed} == "${_file}" ]] && continue 3
            done
            printf '%s\n' "${_file}"
            _already_printed+=( "${_file}" )
        fi
    done

    _files+=( "${_file}" )
done

Saída:

$ ./lsdups < f.txt
f3.txt

Executar como ./lsdups < file .

Tenha em mente que ls output não é a melhor coisa a ser usada, no entanto. O link aborda algumas razões pelas quais você não deve fazer isso.

    
por 06.11.2011 / 15:58
1

O utilitário uniq remove ou lista duplicados. A entrada precisa ser classificada . Como apenas a parte do nome do arquivo é relevante, diga a esses utilitários para ignorar o que está à esquerda dos nomes dos arquivos.

sort -k 1.54 f.txt | uniq -s 54 -cd
    
por 06.11.2011 / 16:53