Existe uma maneira de ver algum progresso de tar por arquivo?

122

Eu tenho alguns arquivos grandes que gostaria de compactar. Eu posso fazer isso com, por exemplo

tar cvfj big-files.tar.bz2 folder-with-big-files

O problema é que eu não consigo ver nenhum progresso, então não tenho idéia de quanto tempo levará ou algo assim. Usando vposso ver pelo menos quando cada arquivo é concluído, mas quando os arquivos são poucos e grandes, isso não é o mais útil.

Existe uma maneira de obter alcatrão para mostrar um progresso mais detalhado? Como uma porcentagem feita ou uma barra de progresso ou tempo estimado restante ou algo assim. Para cada arquivo único ou para todos eles ou ambos.

Svish
fonte

Respostas:

100

Eu prefiro oneliners assim:

tar cf - /folder-with-big-files -P | pv -s $(du -sb /folder-with-big-files | awk '{print $1}') | gzip > big-files.tar.gz

Terá uma saída como esta:

4.69GB 0:04:50 [16.3MB/s] [==========================>        ] 78% ETA 0:01:21

Para OSX (da resposta de Kenji)

tar cf - /folder-with-big-files -P | pv -s $(($(du -sk /folder-with-big-files | awk '{print $1}') * 1024)) | gzip > big-files.tar.gz
soma de verificação
fonte
2
No OSX, du não leva argumento -b, necessário para fallback para: $ ((du sk / pasta-with | awk '{print $ 1}') * 1024))
ıɾuǝʞ
4
Bom, um forro. Você pode explicar isso? Ou isso funciona magicamente de alguma forma?
Kissaki 4/04
2
Ok, eu tenhopv $FILE.tgz | tar xzf - -C $DEST_DIR
Krzysztof Szewczyk
1
Para OS X, eu precisava usar o formulário quadrado suporte para a expansão aritmética, o que fez: tar cf - /folder-with-big-files -P | pv -s $[$(du -sk /folder-with-big-files | awk '{print $1}') * 1024] | gzip > big-files.tar.gzSem essa mudança, eu estava ficando-bash: syntax error near unexpected token ')'
Dean Becker
1
Observe que o progresso não aparece até que o comando du termine, o que pode demorar um pouco, dependendo do tamanho, complexidade e fragmentação do diretório.
Rooster242 10/01
75

Você pode usar o pv para conseguir isso. Para relatar o progresso corretamente, é pvnecessário saber quantos bytes você está jogando nele. Portanto, o primeiro passo é calcular o tamanho (em kbyte). Você também pode soltar completamente a barra de progresso e apenas pvinformar quantos bytes ele viu; relataria um 'feito tanto e tão rápido'.

% SIZE=`du -sk folder-with-big-files | cut -f 1`

E depois:

% tar cvf - folder-with-big-files | pv -p -s ${SIZE}k | \ 
     bzip2 -c > big-files.tar.bz2
akira
fonte
Legal. pvparece não vir com o Mac OS X, mas tentarei fazer isso assim que tiver um computador com o MacPorts. Você poderia explicar o que está fazendo lá? Não tenho certeza do que exatamente a primeira linha faz.
Svish
4
primeira linha: busca informações sobre quantos bytes serão tratados. segunda linha: use o tamanho da primeira linha para permitir que o PV processe 'progresso'. como você está canalizando dados, o pv não sabe quantos bytes mais virão.
akira
Uma adição: SIZE=$(($SIZE * 1000 / 1024))- Eu não sei se isso é uma peculiaridade na minha plataforma em particular, por isso não estou adicionando à resposta: duretorna tamanho onde 1 kb = 1024 bytes, enquanto pvparece estar esperando 1 kb = 1000 bytes. (Estou no Ubuntu 10.04)
Izkata
2
@lzkata, você sempre pode pedir dupara usar o seu tamanho de bloco preferido, por exemplo du -s --block-size=1000, ou apenas trabalhar com bytes simples, por exemplo, largar os k's das chamadas due pv. No entanto, eu esperaria que ambos usassem, 1024salvo indicação em contrário, por exemplo, --siligar du, por exemplo.
Legolas
1
ou simplesmente solte o k-stuff e use bytes simples ( du -sbe pv -ssem nenhum modificador). isso deve acabar com toda a confusão.
Akira
22

melhor barra de progresso ..

apt-get install pv dialog

(pv -n file.tgz | tar xzf - -C target_directory ) \
2>&1 | dialog --gauge "Extracting file..." 6 50

insira a descrição da imagem aqui

Senhor preto
fonte
2
Isso funciona para extração, mas você ainda precisa executar um dos comandos mais complicados para criação (que era a pergunta original). Ainda poderia ser combinado com esses; é apenas mais complicado.
Daniel H
17

Verifique as opções --checkpointe --checkpoint-actionna página de informações do tar (como na minha distribuição, a descrição dessas opções não está contida na página de manual → RTFI).

Consulte https://www.gnu.org/software/tar/manual/html_section/tar_26.html

Com estes (e talvez a funcionalidade de escrever seu próprio comando de ponto de verificação), você pode calcular uma porcentagem…

ajudante
fonte
3
Essa deve ser a resposta correta. Outros apenas explicam ferramentas extras (além de não instaladas por padrão) para obter algo semelhante.
Carmine Giangregorio
@ Sardathrion Talvez porque seja tarespecífico do GNU .
PHK
11

Inspirado pela resposta do ajudante

Outra maneira é usar as taropções nativas

FROMSIZE=`du -sk ${FROMPATH} | cut -f 1`;
CHECKPOINT=`echo ${FROMSIZE}/50 | bc`;
echo "Estimated: [==================================================]";
echo -n "Progess:   [";
tar -c --record-size=1K --checkpoint="${CHECKPOINT}" --checkpoint-action="ttyout=>" -f - "${FROMPATH}" | bzip2 > "${TOFILE}";
echo "]"

o resultado é como

Estimated: [==================================================]
Progess:   [>>>>>>>>>>>>>>>>>>>>>>>

um exemplo completo aqui

campisano
fonte
4

Usando apenas alcatrão

tartem a opção (desde a v1.12) para imprimir informações de status em sinais usando --totals=$SIGNO, por exemplo:

tar --totals=USR1 -czf output.tar input.file
Total bytes written: 6005319680 (5.6GiB, 23MiB/s)

As Total bytes written: [...]informações são impressas em todos os sinais USR1, por exemplo:

pkill -SIGUSR1 tar

Fonte:

Murmel
fonte
3

Acabei de notar o comentário sobre o MacOS e, embora eu ache a solução do @akira (e pv) muito mais elegante, pensei em seguir um palpite e uma rápida solução alternativa na minha caixa do MacOS com tar e enviar um sinal SIGINFO. Curiosamente, funcionou :) se você estiver em um sistema BSD-like, este deve funcionar, mas em uma caixa de Linux, talvez seja necessário enviar um SIGUSR1, e / ou tarpode não funcionar da mesma maneira.

O lado negativo é que ele apenas fornecerá uma saída (no stdout) mostrando a você o quão longe está o arquivo atual, pois acho que não tem idéia do tamanho do fluxo de dados.

Portanto, sim, uma abordagem alternativa seria ativar o alcatrão e enviá-lo periodicamente a SIGINFOs sempre que você quiser saber até que ponto chegou. Como fazer isso?

A abordagem manual ad-hoc

Se você quiser verificar o status de maneira ad-hoc, poderá clicar control-T(como Brian Swift mencionou) na janela relevante que enviará o sinal SIGINFO. Um problema é que ele será enviado para toda a cadeia, acredito que, se você estiver fazendo:

% tar cvf - folder-with-big-files | bzip2 -c > big-files.tar.bz2

Você também verá o relatório bzip2, seu status e o tar:

a folder-with-big-files/big-file.imgload 0.79  cmd: bzip2 13325 running 
      14 0.27u 1.02s 

      adding folder-with-big-files/big-file.imgload (17760256 / 32311520)

Isso funciona muito bem se você quiser apenas verificar se tarestá executando ou está travado ou lento. Você provavelmente não precisa se preocupar muito com problemas de formatação neste caso, pois é apenas uma verificação rápida.

O tipo de abordagem automatizada

Se você sabe que vai demorar um pouco, mas quer algo como um indicador de progresso, uma alternativa seria disparar seu processo de tar e, em outro terminal, calcular o PID e jogá-lo em um script que apenas envia repetidamente um sinal . Por exemplo, se você tiver o seguinte scriptlet (e invoque-o como diz script.sh PID-to-signal interval-to-signal-at):

#!/bin/sh

PID=$1
INTERVAL=$2
SIGNAL=29      # excuse the voodoo, bash gets the translation of SIGINFO, 
               # sh won't..

kill -0 $PID   # invoke a quick check to see if the PID is present AND that
               # you can access it..

echo "this process is $$, sending signal $SIGNAL to $PID every $INTERVAL s"
while [ $? -eq 0 ]; do
     sleep $INTERVAL;
     kill -$SIGNAL $PID;    # The kill signalling must be the last statement
                            # or else the $? conditional test won't work
done
echo "PID $PID no longer accessible, tar finished?"

Se você invocá-lo dessa maneira, como você está segmentando apenas, tarobterá uma saída mais parecida com esta

a folder-with-big-files/tinyfile.1
a folder-with-big-files/tinyfile.2
a folder-with-big-files/tinyfile.3
a folder-with-big-files/bigfile.1
adding folder-with-big-files/bigfile.1 (124612 / 94377241)
adding folder-with-big-files/bigfile.1 (723612 / 94377241)
...

o que eu admito, é meio bonito.

Por último, mas não menos importante - meus scripts estão meio enferrujados; portanto, se alguém quiser entrar e limpar / consertar / melhorar o código, continue sua vida :)

tanantish
fonte
2
Se estiver executando tarna linha de comando, digitar control-Tenviará um SIGINFO. Se este foi em um script que seria feito comkill -INFO pid
Brian Swift
Esqueci completamente control-T, eu claramente se acostumaram a spam muitas janelas do console para o meu bem ..
tanantish
1
porque eu não posso ver -SIGINFO ao fazerkill -l
Felipe Alvarez
2

Inspirado pela resposta de Noah Spurrier

function tar {
  local bf so
  so=${*: -1}
  case $(file "$so" | awk '{print$2}') in
  XZ) bf=$(xz -lv "$so" |
    perl -MPOSIX -ane '$.==11 && print ceil $F[5]/50688') ;;
  gzip) bf=$(gzip -l "$so" |
    perl -MPOSIX -ane '$.==2 && print ceil $F[1]/50688') ;;
  directory) bf=$(find "$so" -type f | xargs du -B512 --apparent-size |
    perl -MPOSIX -ane '$bk += $F[0]+1; END {print ceil $bk/100}') ;;
  esac
  command tar "$@" --blocking-factor=$bf \
    --checkpoint-action='ttyout=%u%\r' --checkpoint=1
}

Fonte

Steven Penny
fonte
17
Um pouco de contexto e explicação, talvez?
Kissaki 4/10/14
1

Se você soubesse o número do arquivo em vez do tamanho total de todos eles:

uma alternativa (menos precisa, mas adequada) é usar a opção -l e enviar no canal unix os nomes dos arquivos em vez do conteúdo dos dados.

Vamos colocar 12345 arquivos no mydir , o comando é:

[myhost@myuser mydir]$ tar cfvz ~/mytarfile.tgz .|pv -s 12345 -l > /dev/null 

você pode conhecer esse valor antecipadamente (por causa do seu caso de uso) ou usar algum comando como find + wc para descobri-lo:

[myhost@myuser mydir]$ find | wc -l
12345
bzimage
fonte
Então, por que não colocar este comando em subcomando? =)
Kirby
tar cfvz ~/mytarfile.tgz . | pv -s $(find . | wc -l) -l > /dev/null. Funciona para você?
Kirby
1

Método baseado em tqdm :

tar -v -xf tarfile.tar -C TARGET_DIR | tqdm --total $(tar -tvf tarfile.tar | wc -l) > /dev/null
J_Zar
fonte
1

No macOS , primeiro verifique se você tem todos os comandos disponíveis e instale os que estão faltando (por exemplo pv) usando o brew .

Se você quiser apenas tar sem compactação , vá com:

tar -c folder-with-big-files | pv -s $[$(du -sk folder-with-big-files | awk '{print $1}') * 1024] > folder-with-big-files.tar

Se você deseja compactar , vá com:

tar cf - folder-with-big-files -P | pv -s $[$(du -sk folder-with-big-files | awk '{print $1}') * 1024] | gzip > folder-with-big-files.tar.gz

Nota: Pode demorar um pouco até a barra de progresso aparecer. Tente uma pasta menor primeiro para garantir que ela funcione e depois vá para a pasta com arquivos grandes.

Pernalonga
fonte
0

Aqui estão alguns números de um backup de prometheus (dados de métricas) no Debian / buster AMD64:

root# cd /path/to/prometheus/
root# tar -cf - ./metrics | ( pv -p --timer --rate --bytes > prometheus-metrics.tar )

Cancelou este trabalho porque não havia espaço em disco suficiente disponível.

Experimentando zstdcomo compressor para tarmonitorar o progresso usando pv:

root# apt-get update
root# apt-get install zstd pv

root# tar -c --zstd -f - ./metrics | ( pv -p --timer --rate --bytes > prometheus-metrics.tar.zst )
10.2GiB 0:11:50 [14.7MiB/s]

root# du -s -h prometheus
62G    prometheus

root# du -s -h prometheus-metrics.tar.zst
11G    prometheus-metrics.tar.zst
dileks
fonte