Script rápido para comparar somas de verificação

0

Eu tenho vários arquivos e preciso verificar suas somas de verificação. Eu tenho um arquivo de texto que se parece com:

soma de verificação <tab> nome_do_arquivo <new line>

Imaginei que usaria isso como um exercício para melhorar meu script de shell. Foi isso que eu fiz e deu certo, só estou curioso para saber se há um jeito melhor. Eu percebo que não é muito flexível (como assumir o formato do arquivo e o algoritmo é 256). Mas eu tentei evitar cat e echo ...:)

Obrigado!

#!/bin/sh

workingDir="/path/to/directory/"
textFile="checksums.txt"
filePath="$workingDir$textFile"

while read a b; do
    shasumOutput=$(/usr/bin/shasum -a 256 "$workingDir$b" | /usr/bin/awk '{ print $1 }')
    if [ "$a" = "$shasumOutput" ]; then
        /usr/bin/printf "$b checksum matches: "$a", "$shasumOutput"\n"
    else
        /usr/bin/printf "$b checksum doesn't match: "$a", "$shasumOutput"\n"
    fi
done < "$filePath" 
    
por MacManager 26.06.2017 / 22:25

1 resposta

1

Como Gohu aponta nos comentários, você está reproduzindo verificando que shasum já faz com sua -c flag.

A entrada para shasum -c deve ser produzida por shasum .

Ignorando isso ...

Seu script parece ok, mas posso comentar sobre algumas coisas nele.

As linhas printf são melhor escritas como printf 'format string' "$var1" "$var2" "etc." , por ex. em vez de

/usr/bin/printf "$b checksum matches: "$a", "$shasumOutput"\n"

use

printf '%s checksum matches: %s, %s\n' "$b" "$a" $shasumOutput"

O ponto inteiro de usar printf é que você tem uma string de formato estático seguida por vários bits de dados variáveis que entram no modelo da string de formato.

Além disso, para evitar $( shasum ... ) e reduzir o número de chamadas para utilitários externos, isso é o que eu teria feito:

#!/bin/sh

checkdir='/some/path'
checkfile="$checkdir/checksums.txt"

while read -r checksum filename; do
    if [ ! -f "$checkdir/$filename" ]; then
        printf 'Not found: %s\n' "$filename"
        continue
    fi

    gsha256sum "$checkdir/$filename" |  {
        read -r realsum name
        if [ "$realsum" != "$checksum" ]; then
            printf 'Mismatch for "%s":\n\t%s != %s\n' \
                "$filename" "$checksum" "$realsum"
        else
            printf '%s OK\n' "$filename"
        fi
    }
done <"$checkfile" >&2

Isso reduz o número de chamadas de utilitário externo (na maioria dos shells) para um (o utilitário SHA256).

O utilitário GNU coreutils para produzir somas de verificação SHA256 no meu sistema OpenBSD é chamado gsha256sum . Estou assumindo que sua saída é idêntica a shasum -a 256 em seu sistema.

Algumas notas:

  • Eu geralmente não coloco / no final dos nomes dos diretórios. Em vez disso, insiro o delimitador ao usar a variável. Dessa forma, posso ver diretamente que $checkdir/checksum.txt é um caminho para um arquivo, enquanto ${checkdir}checksum.txt (ou similar) é mais ambíguo.

  • Eu verifico se o arquivo realmente existe antes de tentar verificar sua soma de verificação.

  • Em vez de analisar a saída do programa SHA256 usando awk , eu o leio da mesma forma que leio a soma de verificação e o nome de arquivo do arquivo de soma de verificação. Eu faço isso em um contexto { ...; } .

  • Estou tratando all a saída do loop como "diagnostic messages" e redireciono tudo para o erro padrão com >&2 após done .

  • Eu não uso caminhos absolutos para utilitários em scripts, a menos que haja uma razão real para isso. printf , por exemplo, é quase sempre um utilitário interno do shell e raramente há um motivo para usar /usr/bin/printf explicitamente.

Você provavelmente poderia se safar com uma única chamada (ou poucas chamadas) para o utilitário SHA256 invocando-a com todos os nomes de arquivos do arquivo de entrada e comparando as somas de verificação daquela chamada, mas o código pode ser um pouco complicado e o esforço não valeria a pena se isso fosse uma coisa única e se o arquivo de entrada não fosse enorme.

    
por 03.02.2018 / 11:30