O que há de errado com o meu script bash?

-1

Suponha que faça :

listar nome de arquivo duplicado por linha, aumentando o mesmo md5sum no diretório atual

Primeiro instale o ambiente:

echo "hello" > file1; cp file1 file2; cp file2 file3;

Script de shell:

#!/bin/bash
#FileName: ls_duplicate.sh

## ls file in size-desc order and long listing format and long-iso timestyle
## -rw-rw-r-- 1 ubuntu ubuntu 6 2017-11-21 13:58 file1
## -rw-rw-r-- 1 ubuntu ubuntu 6 2017-11-21 13:58 file2
## -rw-rw-r-- 1 ubuntu ubuntu 5 2017-11-21 13:58 output
find -maxdepth 1 -type f -exec basename {} \; | xargs ls -lS --time-style=long-iso | awk 'BEGIN { 
getline;getline;
prev_name=$8; prev_size=$5;
}

{
cur_name=$8;
cur_size=$5;

if (prev_size==cur_size)
{
    "md5sum " prev_name | getline;
    prev_md5_sum=$1;

    "md5sum " cur_name | getline;
    cur_md5_sum=$1;

    # print(prev_name, prev_md5_sum, cur_name, cur_md5_sum);  # debug

    ##if the two file is same size and same md5sum, then print duplicate file-name
    if ( prev_md5_sum==cur_md5_sum ) { print prev_name; print cur_name;} 
}

prev_size=cur_size; prev_name=cur_name;
}' | sort -u

Arquivos no diretório atual :

file1 file2 file3 ls_duplicate.sh

Executar script : ./ls_duplicate.sh

Saída:

file1 b1946ac92492d2347c6235b4d2611184 file2 b1946ac92492d2347c6235b4d2611184
file2 -rw-rw-r-- file3 b1946ac92492d2347c6235b4d2611184

então o que está acontecendo aqui -rw-rw-r-- ?

Solução

bem, eu mesmo resolvo isso, em vez de usar

"md5sum " prev_name | getline;
prev_md5_sum=$1;
"md5sum " cur_name | getline;
cur_md5_sum=$1; 

usando em vez

"md5sum " prev_name | getline md5_sum;
split(md5_sum, arr, "  ");
prev_md5_sum=arr[1];

"md5sum " cur_name | getline md5_sum;
split(md5_sum, arr, "  ");
cur_md5_sum=arr[1];

Nota : você precisa mudar isso no script (o script original fez não funcionar).

    
por mipa 21.11.2017 / 07:05

1 resposta

0

Parece que você:

  • obtenha uma lista de arquivos
  • seus tamanhos, etc.
  • em seguida, gere md5sums de arquivos do mesmo tamanho
  • e desses, imprima os com o mesmo md5sum

Eu não vou tentar consertar o código awk. Em vez disso, observe que você está replicando a funcionalidade do comando fdupes . De a página de manual :

Searches  the  given  path for duplicate files. Such files are found by
comparing file sizes and MD5 signatures,  followed  by  a  byte-by-byte
comparison.

Eu sugiro que você o use em vez de escrever scripts complexos para isso.

Caso contrário, a eliminação da verificação de tamanho facilita muito a localização de duplicatas:

$ md5sum * | sort -k1,1 | uniq -w32 -D
b1946ac92492d2347c6235b4d2611184  file1
b1946ac92492d2347c6235b4d2611184  file2
b1946ac92492d2347c6235b4d2611184  file3

Todos os hashes de md5sums têm uma largura de 32 caracteres, por isso é fácil dizer à impressão uniq para comparar apenas esses 32 caracteres e imprimir todas as duplicatas encontradas.

Se você realmente precisa ter uma verificação de tamanho, ela se torna bastante complexa, mas ainda mais simples que seu script. find pode imprimir tamanhos de arquivo, então não há necessidade de trazer ls para o mix:

find . -maxdepth 1 -type f -printf "%s/%P\n" | 
  awk -F/ '       # Use / as delimiter, it wont appear in filename
  s[$1]++ {       # if the file size has appeared before
    if (n[$1]) {  # if the first name hasnt been printed yet
      print n[$1] # print it and delete it
      n[$1] = "";
    }
    print $2;     # print filename with duplicated size
    next
  } {n[$1] = $2}  # save filename for each new size encountered'

Este comando awk imprimirá todos os arquivos cujos tamanhos foram duplicados.

Agora, basta usar o md5sum | sort | uniq pipeline mencionado anteriormente:

find -maxdepth 1 -type f -printf "%s/%P\n" | 
  awk -F/ 's[$1]++ {if (n[$1]){print n[$1]} print $2; n[$1] = ""; next} {n[$1] = $2}' |
  xargs -d '\n' md5sum |
  sort -k1,1 |
  uniq -w32 -D
    
por Olorin 21.11.2017 / 10:27