2010-07-28 11:51:37 +0000 2010-07-28 11:51:37 +0000
133
133

¿Hay alguna forma de ver el progreso del tar por archivo?

Tengo un par de archivos grandes que me gustaría comprimir. Puedo hacerlo con, por ejemplo,

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

El problema es que no puedo ver ningún progreso, así que no tengo ni idea de cuánto tiempo tardará ni nada parecido. Usando v al menos puedo ver cuando se completa cada archivo, pero cuando los archivos son pocos y grandes esto no es lo más útil.

¿Hay alguna forma de hacer que tar muestre un progreso más detallado? Como un porcentaje hecho o una barra de progreso o tiempo estimado restante o algo así. Ya sea para cada archivo individual o para todos ellos o para ambos.

Respuestas (13)

109
109
109
2013-10-25 08:15:15 +0000

Prefiero los oneliners como este:

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

Tendrá una salida como esta

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

Para OSX (de la respuesta 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
77
77
77
2010-07-28 12:01:07 +0000

Puede utilizar pv para conseguirlo. Para informar correctamente del progreso, pv necesita saber cuántos bytes le estás lanzando. Así que el primer paso es calcular el tamaño (en kbytes). También puedes dejar de lado la barra de progreso y dejar que pv te diga cuántos bytes ha visto; informaría de un “hecho tanto y tan rápido”.

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

Y entonces

% tar cvf - folder-with-big-files | pv -p -s ${SIZE}k | \ 
     bzip2 -c > big-files.tar.bz2
23
23
23
2012-08-28 08:26:14 +0000

mejor barra de progreso..

apt-get install pv dialog

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

17
17
17
2011-08-04 20:53:06 +0000

Comprueba las opciones --checkpoint y --checkpoint-action en la página de información de tar (en cuanto a mi distribución, la descripción de estas opciones no está contenida en la página man → RTFI).

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

Con estos (y tal vez la funcionalidad para escribir su propio comando de chequeo), puede calcular un porcentaje…

11
11
11
2017-07-16 00:22:25 +0000

Inspirado en la respuesta de helper

Otra forma es utilizar las opciones nativas tar 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 "]"

el resultado es como

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

un ejemplo completo aquí

8
8
8
2018-06-15 05:03:41 +0000

Usando sólo tar

tar tiene la opción (desde la v1.12) de imprimir información de estado en las señales que usan --totals=$SIGNO, por ejemplo

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

La información Total bytes written: [...] se imprime en cada señal USR1, por ejemplo

pkill -SIGUSR1 tar

Fuente:

3
3
3
2012-04-21 20:44:39 +0000

Acabo de notar el comentario sobre MacOS, y aunque creo que la solución de @akira (y pv) es mucho más limpia, pensé en perseguir una corazonada y un rápido juego en mi caja MacOS con tar y enviando una señal SIGINFO. Curiosamente, funcionó :) si estás en un sistema tipo BSD, esto debería funcionar, pero en una caja Linux, podrías necesitar enviar un SIGUSR1, y/o tar podría no funcionar de la misma manera.

El lado negativo es que sólo le proporcionará una salida (en stdout) que le mostrará lo lejos que está del archivo actual, ya que supongo que no tiene idea de lo grande que es el flujo de datos que está recibiendo.

Así que sí, un enfoque alternativo sería disparar tar y enviarle periódicamente SIGINFOs cada vez que quieras saber hasta dónde ha llegado. ¿Cómo hacer esto?

El enfoque ad-hoc, manual

Si quiere ser capaz de comprobar el estado de forma ad-hoc, puede pulsar control-T (como Brian Swift mencionó) en la ventana correspondiente que enviará la señal SIGINFO. Un problema con esto es que lo enviará a toda tu cadena, creo, así que si estás haciendo:

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

También verás que bzip2 informa de su estado junto con 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)

Esto funciona bien si sólo quieres comprobar si ese tar que estás ejecutando está atascado, o simplemente es lento. Probablemente no tengas que preocuparte demasiado por los problemas de formato en este caso, ya que es sólo una comprobación rápida..

El tipo de aproximación automatizada

Si sabes que va a tomar un tiempo, pero quieres algo como un indicador de progreso, una alternativa sería disparar tu proceso tar y en otra terminal calcular su PID y luego lanzarlo en un script que simplemente envíe repetidamente una señal. Por ejemplo, si tienes el siguiente scriptlet (y lo invocas como digamos 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?"

Si lo invocas de esta manera, ya que estás apuntando sólo a tar obtendrás una salida más como 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)
...

que admito, es bastante bonita.

Por último, pero no por ello menos importante, mi programación está un poco oxidada, así que si alguien quiere ir a limpiar/corregir/mejorar el código, que se anime :)

2
2
2
2012-04-18 01:00:19 +0000

Inspirado en la respuesta 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
}

[Fuente

1
1
1
2017-09-15 12:38:27 +0000

Si conoce el número de archivo en lugar del tamaño total de todos ellos:

una alternativa (menos precisa pero adecuada) es utilizar la opción -l y enviar en la tubería unix los nombres de los archivos en lugar del contenido de los datos.

tengamos 12345 archivos en mydir, el comando es:

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

puedes conocer ese valor de antemano (por tu caso de uso) o usar algún comando como find+wc para descubrirlo:

[myhost@myuser mydir]$ find | wc -l
12345
1
1
1
2019-09-02 20:05:09 +0000

En macOS , primero asegúrate de que tienes todos los comandos disponibles, e instala los que faltan (por ejemplo, pv) usando brew .

Si sólo quiere tar sin compresión , vaya con:

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

Si quiere comprimir , vaya con:

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: Puede tardar un poco en aparecer la barra de progreso. Pruebe primero en una carpeta más pequeña para asegurarse de que funciona, y luego pase a la carpeta con archivos grandes.

1
1
1
2018-04-27 06:44:10 +0000

Método basado en tqdm :

tar -v -xf tarfile.tar -C TARGET_DIR | tqdm --total $(tar -tvf tarfile.tar | wc -l) > /dev/null
0
0
0
2019-09-13 15:39:11 +0000

Estos son algunos números de una copia de seguridad de prometheus (datos métricos) en Debian/buster AMD64:

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

Cancelado este trabajo porque no había suficiente espacio en disco disponible.

Experimentando con zstd como compresor para tar con la monitorización del progreso 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
0
0
0
2020-02-25 22:54:21 +0000

En mi uso diario no necesito saber el progreso exacto a nivel de porcentaje de la operación, sólo si está funcionando y (a veces) cuánto le falta para terminar.

Esta necesidad la resuelvo mínimamente mostrando el número de archivos procesados en su propia línea; en Bash:

let n=0; tar zcvf files.tgz directory | while read LINE; do printf "\r%d" $((n++)) ; done ; echo

Como uso mucho esto, definí un alias de función en . bashrc:

function pvl { declare -i n=0; while read L ; do printf "\r%d" $((++n)) ; done ; echo ; }

Entonces simplemente:

tar zcvf files.tgz directory | pvl

Puedo calcular el número de archivos por adelantado si es necesario con find directory | wc -l (¡O mejor usando la misma función mostrada [find directory | pvl] para aplastar mi impaciencia!)

Otro ejemplo, establecer los derechos para un sitio web virtual (después de eso, un chown -R es rápido porque los nombres de los archivos están en la caché del sistema de archivos):

find /site -print -type d -exec chmod 2750 "{}" \; -o -type f -exec chmod 640 "{}" | pvl

Es cierto que este procesamiento lateral podría ralentizar la operación principal, pero creo que imprimir un carácter de retorno y unos pocos dígitos no puede ser demasiado costoso (¡además, esperar a que aparezca el siguiente signo de igualdad o a que cambie el dígito de porcentaje se antoja lento comparado con la subjetiva velocidad de cambio de dígitos!)