AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 495477
Accepted
EmmaV
EmmaV
Asked: 2019-01-20 08:29:33 +0800 CST2019-01-20 08:29:33 +0800 CST 2019-01-20 08:29:33 +0800 CST

Usando pv com md5sum

  • 772

Eu usei md5sumpara pvverificar 4 GiB de arquivos que estão no mesmo diretório:

md5sum dir/* | pv -s 4g | sort

O comando é concluído com sucesso em cerca de 28 segundos, mas pva saída de 's está toda errada. Este é o tipo de saída que é exibida por toda parte:

219 B 0:00:07 [ 125 B/s ] [>                                ]  0% ETA 1668:01:09:02

É assim sem o -s 4ge | sorttambém. Eu também tentei com arquivos diferentes.

Eu tentei usar pvcom cate a saída foi boa, então o problema parece ser causado por md5sum.

pipe hashsum
  • 5 5 respostas
  • 1779 Views

5 respostas

  • Voted
  1. Best Answer
    Kusalananda
    2019-01-20T09:14:13+08:002019-01-20T09:14:13+08:00

    O pvutilitário é "fantasioso cat", o que significa que você pode usar pvna maioria das situações em que usaria cat.

    Usando catcom md5sum, você pode calcular a soma de verificação MD5 de um único arquivo com

    cat file | md5sum
    

    ou, com pv,

    pv file | md5sum
    

    Infelizmente, porém, isso não permite md5suminserir o nome do arquivo em sua saída corretamente.

    Agora, felizmente, pvé um , e em alguns catsistemas (Linux), é capaz de observar os dados sendo passados ​​por outro processo. Isso é feito usando sua -dopção com o ID do processo desse outro processo.

    Isso significa que você pode fazer coisas como

    md5sum dir/* | sort >sums &
    sleep 1
    pv -d "$(pgrep -n md5sum)"
    

    Isso permitiria pvobservar o md5sumprocesso. O sleepestá lá para permitir md5sumque o , que está sendo executado em segundo plano, seja iniciado corretamente. pgrep -n md5sumretornaria o PID do md5sumprocesso iniciado mais recentemente que você possui. pvsairá assim que o processo que está sendo observado terminar.

    Eu testei essa maneira específica de execução pvalgumas vezes e geralmente parece funcionar bem, mas às vezes parece parar de produzir qualquer coisa como md5sumalterna para o próximo arquivo. Às vezes, parece gerar tarefas espúrias em segundo plano no shell.

    Provavelmente seria mais seguro executá-lo como

    md5sum dir/* >sums &
    sleep 1
    pv -W -d "$!"
    sort -o sums sums
    

    A -Wopção fará com pvque espere até que haja dados reais sendo transferidos, embora isso também nem sempre pareça funcionar de maneira confiável.

    • 11
  2. ozzy
    2019-01-20T09:48:06+08:002019-01-20T09:48:06+08:00

    Os dados que você está alimentando pelo pipe não são os dados dos arquivos que md5sumestão sendo processados, mas sim a md5sumsaída, que, para cada arquivo, consiste em uma linha composta por: o MD5-hash, dois espaços e o nome do arquivo. Como sabemos disso com antecedência, podemos informar pvadequadamente, de modo a permitir que ele exiba um indicador de progresso preciso. Existem duas maneiras de fazê-lo.

    O primeiro método preferido (sugerido por frostschutz) faz uso do fato de md5sumgerar uma linha por arquivo processado e do fato de pvpossuir um modo de linha que conta linhas em vez de bytes. Neste modo pvsó irá mover a barra de progresso quando encontrar uma nova linha no throughput, ou seja, por arquivo finalizado por md5sum. No Bash, esse primeiro método pode ficar assim:

    set -- *.iso; md5sum "$@" | pv --line-mode -s $# | sort
    

    O setbuiltin é usado para definir os parâmetros posicionais para os arquivos a serem processados ​​(o *.isopadrão de shell é expandido pelo shell). md5sumé então instruído a processar esses arquivos ( $@se expande para os parâmetros posicionais) e, pvno modo de linha, moverá o indicador de progresso toda vez que um arquivo for processado / uma linha for gerada por md5sum. Notavelmente, pvé informado do número total de linhas que pode esperar ( -s $#), pois o parâmetro especial do shell $#se expande para o número de argumentos posicionais.

    O segundo método não é baseado em linha, mas em byte. Com md5sumisso desnecessariamente complicado, mas algum outro programa pode não produzir linhas, mas, por exemplo, dados contínuos, e essa abordagem pode ser mais prática. Eu ilustro com md5sumembora. A ideia é calcular a quantidade de dados que md5sum(ou algum outro programa) vai produzir, e usar isso para informar pv. No Bash, isso pode ter a seguinte aparência:

    os=$(( $( ls -1 | wc -c ) + $( ls -1 | wc -l ) * 34 ))
    md5sum * | pv -s $os | sort
    

    A primeira linha calcula a estimativa do tamanho de saída ( os): o primeiro termo é o número de bytes necessários para codificar os nomes dos arquivos (incluindo nova linha), o segundo termo o número de bytes usados ​​para codificar os hashes MD5 (32 bytes cada), mais 2 vagas. Na segunda linha, informamos pvque a quantidade de dados esperada é osbytes, para que possa mostrar um indicador de progresso preciso até 100% (qual indicador é atualizado por arquivo md5summed finalizado).

    Obviamente, ambos os métodos são práticos apenas no caso de vários arquivos serem processados. Além disso, deve-se notar que, uma vez que a saída de md5sumnão está relacionada à quantidade de tempo que o md5sumprograma tem que gastar processando os dados subjacentes, o indicador de progresso pode ser considerado um tanto enganoso. Por exemplo, no segundo método, o arquivo com o nome mais curto produzirá a atualização de progresso mais baixa, mesmo que possa ser o maior em tamanho. Então, novamente, se todos os arquivos tiverem tamanhos e nomes semelhantes, isso não deve importar muito.

    • 5
  3. frostschutz
    2019-01-20T10:47:05+08:002019-01-20T10:47:05+08:00

    Aqui está um truque sujo para obter progresso por arquivo:

    for f in iso/*
    do
        pv "$f" | (
            cat > /dev/null &
            md5sum "$f"
            wait
        )
    done
    

    O que isso parece:

    4.15GiB 0:00:32 [ 130MiB/s] [================================>] 100%            
    0db0b36fc7bad7b50835f68c369e854c  iso/KNOPPIX_V7.6.1DVD-2016-01-16-EN.iso
     792MiB 0:00:06 [ 130MiB/s] [================================>] 100%            
    97537db63e61d20a5cb71d29145b2937  iso/archlinux-2016.10.01-dual.iso
     843MiB 0:00:06 [ 129MiB/s] [================================>] 100%            
    1b5dc31e038499b8409f7d4d720e3eba  iso/lubuntu-16.04-desktop-i386.iso
     259MiB 0:00:02 [ 130MiB/s] [=========>                        ] 30% ETA 0:00:04
    ...
    

    Agora, isso faz várias suposições. Em primeiro lugar, essa leitura de dados é mais lenta do que o hash. pvEm segundo lugar, esse sistema operacional armazenará em cache a E/S para que os dados não sejam (fisicamente) lidos duas vezes , embora md5sumsejam leitores completamente independentes.

    O bom de um hack tão sujo e sujo é que você pode adaptá-lo facilmente para fazer uma barra de progresso em todos os dados, não apenas em um arquivo. E ainda fazer coisas estranhas como classificar a saída depois.

    pv iso/* | (
        cat > /dev/null &
        md5sum iso/* | sort
        wait
    )
    

    Como é (em andamento):

    15.0GiB 0:01:47 [ 131MiB/s] [===========================>      ] 83% ETA 0:00:21
    

    Como é (acabado):

    18.0GiB 0:02:11 [ 140MiB/s] [================================>] 100%            
    0db0b36fc7bad7b50835f68c369e854c  iso/KNOPPIX_V7.6.1DVD-2016-01-16-EN.iso
    155603390e65f2a8341328be3cb63875  iso/systemrescuecd-x86-4.2.0.iso
    1b5dc31e038499b8409f7d4d720e3eba  iso/lubuntu-16.04-desktop-i386.iso
    1b6ed6ff8d399f53adadfafb20fb0d71  iso/systemrescuecd-x86-4.4.1.iso
    25715326d7096c50f7ea126ac20eabfd  iso/openSUSE-13.2-KDE-Live-i686.iso
    ...
    

    Agora, isso é para os hacks. Verifique outras respostas para soluções adequadas. ;-)

    • 2
  4. fra-san
    2019-01-20T10:23:07+08:002019-01-20T10:23:07+08:00

    Como já apontado nos comentários e outras respostas:

    1. Você está canalizando pvapenas md5suma saída de: checksums e nomes de arquivos; assim, pva barra de progresso do 's não é capaz de mostrar quantos dados md5sumestão sendo lidos.
    2. Um tamanho de 4 GB será, obviamente, muito para isso. Além disso, fornecer pvo tamanho do(s) arquivo(s) que você está canalizando (manualmente, com -s) é inconveniente.

    Encaminhar o conteúdo de seus arquivos pve, em seguida md5sum, fornecerá uma barra de progresso, mas os nomes dos arquivos serão perdidos.

    Este código é uma maneira não tão elegante de ter ambos - uma barra de progresso significativa e nomes de arquivos com somas de verificação:

    #!/bin/sh
    
    for file in "$@"; do
        pv -- "$file" |
        md5sum |
        sed 's/-$//' |
        printf '%s%s\n' "$(cat -)" "$file"
    done
    

    O script deve ser invocado como:

    ./script dir/*
    

    É claro que você pode declará-lo como uma função, para evitar ter que digitar seu caminho para chamá-lo (ou adicioná-lo ao seu PATH):

    function pvsum () {
        for file in "$@"; do
            pv -- "$file" |
              md5sum |
              sed 's/-$//' |
              printf '%s%s\n' "$(cat -)" "$file"
        done
    }
    

    Dessa forma, o comando pvsum dir/* | sortserá equivalente ao seu md5sum dir/* | pv -s <size> | sort.

    Sua saída:

    $ ./testscript testdir/*
    4.00GiB 0:00:09 [ 446MiB/s] [==============================>] 100%            
    9dab5f8add1f699bca108f99e5fa5342  testdir/file1
    1.00GiB 0:00:02 [ 447MiB/s] [==============================>] 100%            
    06a738a71e3fd3119922bdac259fe29a  testdir/file2
    

    O que faz:

    • Ele percorre os arquivos fornecidos e, para cada um:
      • Encaminha o arquivo pvpara md5sum, mostrando a barra de progresso padrão.
      • sedé usado para remover o -impresso por md5sum(que está lendo da entrada padrão); isso também tenta tornar a saída adequada para ser consumida por md5sum -c(graças a frostschutz por apontar isso) 1 .
      • Imprime a soma de verificação seguida pelo nome do arquivo na saída padrão.

    Sobre sort:

    Não tenho certeza sobre seus resultados esperados, então simplesmente ignorei. Como pvgrava sua barra de progresso no erro padrão, canalizar tudo para sortdesanexar pva saída de md5sum's da saída de .
    De qualquer forma, você pode simplesmente anexar | sortdepois doneno código acima e verificar se o resultado está bom para você.


    1 Observe que a saída do código mostrado acima não será adequada md5sum -cse os nomes dos arquivos incluírem novas linhas. Manipular novas linhas é possível, mas algumas versões de md5sumse comportam de maneira diferente a esse respeito (veja, por exemplo, respostas a esta pergunta ), tornando uma solução geral não fácil (e fora do escopo desta resposta).

    Assumindo uma versão recente do md5sum, uma tentativa de resolver esse problema pode ser:

    for file in "$@"; do
        pv -- "$file" |
        md5sum |
        sed 's/-$//' |
        printf '%s%s\n' "$(cat -)" "$file" |
        sed -n 'H; 1h; $!d; g; s/\\/\\\\/g; s/\n/\\n/g; t x; p; q; :x s/^/\\/; p;'
    done
    

    Onde a única adição, a final sed, irá:

    • Coloque toda a entrada, soma de verificação e nome do arquivo atual, no espaço de padrão, pois ele pode conter novas linhas: Hacrescenta uma nova linha e um espaço de padrão atual ao espaço de espera; 1hsubstitui anterior H, apenas para a primeira linha, fazendo o mesmo, mas sem acrescentar uma nova linha; $!dinicia um novo ciclo se a linha atual não for a última; gcoloca o conteúdo do espaço de espera no espaço do padrão.
    • Fuja com uma barra invertida ( \) qualquer barra invertida no espaço de padrão resultante.
    • Substitua por \nqualquer nova linha no espaço de padrão resultante.
    • Somente se pelo menos uma barra invertida ou nova linha tiver sido substituída ( t x: branch to label x), uma barra invertida será adicionada no início da soma de verificação para sinalizar md5sum -cque algo não deve ser escapado; caso contrário, simplesmente desista. Em ambos os casos, imprima ( p) o espaço do padrão na saída padrão antes de sair (a opção -ndesativa a impressão automática).
    • 1
  5. sudodus
    2019-01-20T19:21:59+08:002019-01-20T19:21:59+08:00

    Eu também gostei de domar o 'gato chique', pv, para md5sum:-)

    • Eu acho que meu shellscript está bastante estável agora
    • Há uma usagesaída, se você não inserir o padrão corretamente.
    • Funciona com curingas, mas não recorre a subdiretórios
    • Você pode inserir mais de um padrão, por exemplo".* *"
    • Existe uma opção de verbosidade que ativa a verificação do md5sums... OK
    • Você pode redirecionar a saída relevante para um arquivo; a saída da visualização do processo pvpermanecerá na {tela/janela do terminal}
    • Existem dois pvprocessos em um loop for, um global e um para cada arquivo, o global pv'só conta os arquivos', e o outro mede a velocidade e a quantidade de dados transferidos
    • As sequências de escape ANSI são usadas para manter a visualização do processo em uma posição estável

    Eu uso o name md5summer, faço o shellscript executável e coloco em um diretório em PATH (meu ~/bindiretório, você pode preferir /usr/local/bin).

    #!/bin/bash
    
    # date      sign     comment
    # 20190119  sudodus  created md5summer version 1.0
    
    if [ "$1" == "-v" ]
    then
     verbose=true
     shift
    else
     verbose=false
    fi
    if [ $# -ne 1 ]
    then
     echo "Usage:    $0  [-v]  <pattern>"
     echo "Example:  $0  '*.iso'      # notice the quotes"
     echo "          $0  -v  '*.iso'  # verbose"
     exit
    fi
    tmpstr=$(find $1 -maxdepth 0 -type f 2> /dev/null)
    if [ "$tmpstr" == "" ]
    then
     echo "No such file '$1'. Try another pattern!"
     exit
    fi
    
    tmpdir=$(mktemp -d)
    tmpfil="$tmpdir/fil1"
    tmpfi2="$tmpdir/fil2"
    resetvid="\0033[0m"
    prev2line="\0033[2F"
    next2line="\0033[2E"
    
    sln=1
    cln=0
    cnt=0
    for i in $1
    do
     if test -f "$i"
     then
      cln=$((cln+1))
      tmp=$(find -L "$i" -printf "%s")
      cnt=$((cnt+tmp))
     fi
    done
    echo "
                        number of files = $cln
                        total file size = $cnt B ~ $(($cnt/2**20)) MiB
    "
    for i in $1
    do
     if test -f "$i"
     then
      tmpnam=$(echo -n "$i")
      tmpsum=$(< "$i" pv -ptrbs "$cnt" | md5sum)
      sleep 0.05
      echo "$sln" | pv -ls "$cln" > /dev/null
      sleep 0.05
      sln="$sln
    $i"
      sleep 0.05
      printf "${tmpsum/\-}${tmpnam}\n" >> "$tmpfil"
      echo -ne "$prev2line" > /dev/stderr
     fi
    done
    
    sync
    sleep 0.1
    echo -ne "$next2line" > /dev/stderr
    
    echo "-----"
    if $verbose
    then
     sort -k2 "$tmpfil" | tee "$tmpfi2" | md5sum -c
     echo "-----"
     cat "$tmpfi2"
    else
     sort -k2 "$tmpfil"
    fi
    sleep 0.5
    sync
    rm -r "$tmpdir"
    

    Exemplo de demonstração

    Uso

    $ md5summer 
    Usage:    /home/sudodus/bin/md5summer  [-v]  <pattern>
    Example:  /home/sudodus/bin/md5summer  '*.iso'      # notice the quotes
              /home/sudodus/bin/md5summer  -v  '*.iso'  # verbose
    

    Eu testei neste diretório

    $ ls -1a
    .
    ..
    'filename with spaces'
    md5summer
    md5summer1
    md5summer2
    subdir
    .ttt
    zenity-info-message.png
    

    Uso normal mais padrão para ver arquivos ocultos

    $ md5summer ".* *"
    
                        number of files = 6
                        total file size = 12649 B ~ 0 MiB
    
    8,32KiB 0:00:00 [ 156MiB/s] [=============================>                ] 67%
    6,00  0:00:00 [ 133k/s] [====================================>] 100%            
    -----
    184d0995cc8b6d8070f89f15caee35ce  filename with spaces
    28227139997996c7838f07cd4c630ffc  md5summer
    3383b86a0753e486215280f0baf94399  md5summer1
    28227139997996c7838f07cd4c630ffc  md5summer2
    31cd03f64a466e680e9c22fef4bcf14b  .ttt
    670b8db45e57723b5f1b8a63399cdfa1  zenity-info-message.png
    

    Saída detalhada mais padrão para ver arquivos ocultos

    $ md5summer -v ".* *"
    
                        number of files = 6
                        total file size = 12649 B ~ 0 MiB
    
    8,32KiB 0:00:00 [ 184MiB/s] [=============================>                ] 67%
    6,00  0:00:00 [ 133k/s] [====================================>] 100%            
    -----
    filename with spaces: OK
    md5summer: OK
    md5summer1: OK
    md5summer2: OK
    .ttt: OK
    zenity-info-message.png: OK
    -----
    184d0995cc8b6d8070f89f15caee35ce  filename with spaces
    28227139997996c7838f07cd4c630ffc  md5summer
    3383b86a0753e486215280f0baf94399  md5summer1
    28227139997996c7838f07cd4c630ffc  md5summer2
    31cd03f64a466e680e9c22fef4bcf14b  .ttt
    670b8db45e57723b5f1b8a63399cdfa1  zenity-info-message.png
    

    Redirecionamento para um arquivo, primeiro a saída da tela

    $ md5summer ".* *" > subdir/save
    8,32KiB 0:00:00 [ 180MiB/s] [=============================>                ] 67%
    6,00  0:00:00 [ 162k/s] [====================================>] 100%            
    

    e, em seguida, a saída salva

    $ cat subdir/save 
    
                        number of files = 6
                        total file size = 12649 B ~ 0 MiB
    
    -----
    184d0995cc8b6d8070f89f15caee35ce  filename with spaces
    28227139997996c7838f07cd4c630ffc  md5summer
    3383b86a0753e486215280f0baf94399  md5summer1
    28227139997996c7838f07cd4c630ffc  md5summer2
    31cd03f64a466e680e9c22fef4bcf14b  .ttt
    670b8db45e57723b5f1b8a63399cdfa1  zenity-info-message.png
    

    Verificando arquivos iso

    $ md5summer "*.iso"
    
                        number of files = 10
                        total file size = 7112491008 B ~ 6783 MiB
    
    28,0MiB 0:00:00 [ 160MiB/s] [>                                             ]  0%
    10,0  0:00:00 [ 204k/s] [====================================>] 100%            
    -----
    7a27fdd46a63ba4375896891826c1c88  debian-live-8.6.0-amd64-lxde-desktop.iso
    d70eec28cdbdee7f7aa95fb53b9bfdac  debian-live-8.7.1-amd64-standard.iso
    382cfbe621ca446d12871b8945b50d20  debian-live-8.8.0-amd64-standard.iso
    44473dfe2ee1aad0f71506f1d5862457  debian-live-8.8.0-i386-standard.iso
    f396b3532fa84059e7738c3c1827bada  debian-live-9.3.0-amd64-cinnamon.iso
    8f6def28ae7cbefa0a6e59407c884466  debian-live-9.6.0-amd64-cinnamon.iso
    90b1815da0a5bf4ee4b00eec2b5d3587  debian-testing-amd64-netinst_2017-07-28.iso
    8f75074ab98e166b7469299d3e459ac6  mini-amd64-2016-01-21-daily.iso
    e580266fba58eb34b05bf6e13f51a047  mini-jessie-32.iso
    646c109a9a16c0527ce1c7afa922e2ed  mini-jessie-64.iso
    
    • 1

relate perguntas

  • Como canalizar um 'sim' ou 'y' em um programa enquanto é invocado com 'sudo' no bash?

  • Passe o identificador para o pipeline stdin down

  • Como canalizar um comando bash e manter Ctrl + C funcionando?

  • Por que canalizar `mysql` para 'tail' altera o formato de saída?

  • ordem de substituição de processos `te` e `bash`

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve