Compare um arquivo antigo com um novo, mas ignore linhas que só existem no novo arquivo?

7

Eu tenho dois arquivos:

  1. oldlist - contém uma lista de arquivos e um hash md5 para cada arquivo. Isso foi gerado há um ano.
  2. newlist - Também contém uma lista de arquivos e um hash md5 para cada arquivo. No entanto, alguns arquivos foram alterados (por exemplo, o hash md5 é diferente) e alguns novos arquivos foram adicionados.

Gostaria de ver todas as diferenças entre oldlist e newlist , mas quero ignorar todos os arquivos que não existem em oldlist .

Ou seja, não me importo com novos arquivos. Eu só quero comparar os hashes md5 para cada arquivo antigo, para que eu possa ver se algum arquivo foi alterado no último ano.

Eu tentei diff e comm , mas ainda não encontrou uma solução.

    
por Stefan Lasiewski 08.09.2011 / 00:32

4 respostas

5

Use join para combinar linhas correspondentes dos dois arquivos. Supondo que os nomes dos arquivos vêm após as somas de verificação (como em md5sum output) e não contêm espaço em branco, isso imprimirá todos os nomes de arquivos presentes nas duas listas, junto com a soma de verificação antiga e a nova soma de verificação:

join -1 2 -2 2 <(sort -k 2 oldlist) <(sort -k 2 newlist)

Para ver também novos arquivos, passe a opção -a para join . Um pouco de pós-processamento de saída irá remover os nomes de arquivo para os quais a soma de verificação não mudou.

join -a 2 -1 2 -2 2 <(sort -k 2 oldlist) <(sort -k 2 newlist) |
awk '$2 != $3'
    
por 08.09.2011 / 01:18
3

Você poderia fazer isso com awk sozinho:

$ awk 'FNR==NR   { o[$2]=$1; next }       !o[$2] { print $0, "NEW"; next } 
       $1!=o[$2] { print $0, "CHANGED" }' newlist oldlist

(Observe que o suposto formato dos arquivos é o formato de saída md5sum : "md5 filename".)

Atualizar : explicação passo-a-passo de como o awk one-liner funciona.

awk 'FNR==NR { # if current record number==overall record number (still processing the first file)
  o[$2]=$1     # store the record in array o: the key is the file name, the value is the md5
  next         # go to next record (do not execute the rest of the code)
}
# reaching this point means we are processing the second input file
!o[$2] {       # if array o not contains item with the current record's file name
  print $0, "NEW" # print the current record and specify that it's new
  next         # go to next record (do not execute the rest of the code)
}
# reaching this point means array o contains item with the current file name
$1!=o[$2] {    # if the current md5 is not equal with the md5 save for the current file name
  print $0, "CHANGED" # print the current record and specify it's changed
}' newlist oldlist
    
por 08.09.2011 / 09:26
2

Se eu entendi sua pergunta corretamente, então comm pode realmente fazer o que você quer. Eu sugeriria pesquisar em comm --help

especificamente

  -1              suppress column 1 (lines unique to FILE1)
  -2              suppress column 2 (lines unique to FILE2)
  -3              suppress column 3 (lines that appear in both files)

então comm newFile oldFile -1 -3 fará o que você quiser.

    
por 09.09.2011 / 11:33
1

Suponha que os arquivos pareçam (separados por espaços):

file1 md5sum1
file2 md5sum2

Solução simples:

# get only the files:
cut -f 1 -d " " oldlist > oldlist.files 

# from newlist, take only files which were also in the oldlist (updated files)
grep -w -F -f oldlist.files newlist > newlist.updated_files

E então você pode comparar os dois arquivos (após a classificação):

sort -u oldlist > oldlist.su
sort -u newlist.updated_files > newlist.updated_files.su
diff oldlist.su newlist.updated_files.su
    
por 08.09.2011 / 16:19