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

Gibt es eine Möglichkeit, den tar-Fortschritt pro Datei zu sehen?

Ich habe ein paar große Dateien, die ich gerne komprimieren würde. Ich kann das zum Beispiel mit

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

machen. Das Problem ist, dass ich keinen Fortschritt sehen kann, also habe ich keine Ahnung, wie lange es dauern wird oder so etwas. Mit v kann ich zumindest sehen, wann jede Datei fertig ist, aber wenn die Dateien wenige und groß sind, ist das nicht sehr hilfreich.

Gibt es eine Möglichkeit, wie ich tar dazu bringen kann, einen detaillierteren Fortschritt anzuzeigen? Zum Beispiel einen Prozentsatz oder einen Fortschrittsbalken oder die geschätzte verbleibende Zeit oder so etwas. Entweder für jede einzelne Datei oder für alle Dateien oder beides.

Antworten (13)

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

Ich bevorzuge Oneliner wie diesen:

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

Es wird eine Ausgabe wie diese haben:

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

Für OSX (aus Kenjis Antwort)

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

Sie können pv verwenden, um dies zu erreichen. Um den Fortschritt korrekt zu melden, muss pv wissen, wie viele Bytes Sie auf ihn werfen. Der erste Schritt besteht also darin, die Größe (in kByte) zu berechnen. Sie können den Fortschrittsbalken auch komplett weglassen und pv einfach sagen lassen, wie viele Bytes es gesehen hat; es würde dann ein ‘so viel und so schnell erledigt’ melden.

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

Und dann:

% 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

besserer Fortschrittsbalken..

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

Schauen Sie sich die Optionen --checkpoint und --checkpoint-action auf der tar-Infoseite an (wie bei meiner Distribution ist die Beschreibung für diese Optionen nicht in der Manpage enthalten → RTFI).

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

Mit diesen (und vielleicht der Funktionalität, einen eigenen Checkpoint-Befehl zu schreiben), können Sie einen Prozentsatz berechnen…

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

Inspiriert von helper’s answer

Eine andere Möglichkeit ist die Verwendung der nativen tar Optionen

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 "]"

das Ergebnis ist wie

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

ein vollständiges Beispiel hier

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

Nur tar

tar hat die Option (seit v1.12), Statusinformationen auf Signale mit --totals=$SIGNO zu drucken, z. B.:

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

Die Total bytes written: [...]-Information wird auf jedes USR1-Signal gedruckt, z. B.:

pkill -SIGUSR1 tar

Quelle:

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

Ich habe gerade den Kommentar über MacOS bemerkt, und obwohl ich denke, dass die Lösung von @akira (und pv) viel ordentlicher ist, dachte ich, ich würde einer Vermutung nachgehen und einen schnellen Playaround in meiner MacOS-Box mit tar und dem Senden eines SIGINFO-Signals durchführen. Lustigerweise hat es funktioniert :) wenn Sie auf einem BSD-ähnlichen System sind, sollte das funktionieren, aber auf einem Linux-Rechner müssen Sie vielleicht ein SIGUSR1 senden, und/oder tar funktioniert vielleicht nicht auf die gleiche Weise.

Der Nachteil ist, dass es Ihnen nur eine Ausgabe (auf stdout) liefert, die Ihnen zeigt, wie weit es mit der aktuellen Datei ist, da ich vermute, dass es keine Ahnung hat, wie groß der Datenstrom ist, den es bekommt.

Also ja, eine alternative Herangehensweise wäre, tar zu starten und ihm periodisch SIGINFOs zu schicken, wann immer Sie wissen wollen, wie weit es gekommen ist. Wie man das macht?

Der ad-hoc, manuelle Ansatz

Wenn Sie in der Lage sein wollen, den Status ad-hoc zu überprüfen, können Sie control-T (wie Brian Swift erwähnte) im entsprechenden Fenster drücken, was das SIGINFO-Signal sendet. Ein Problem dabei ist, dass es an die gesamte Kette gesendet wird, wenn Sie also Folgendes tun:

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

Sie werden auch sehen, dass bzip2 seinen Status zusammen mit tar meldet:

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)

Das funktioniert gut, wenn Sie nur überprüfen wollen, ob das tar, das Sie ausführen, feststeckt oder einfach langsam ist. Sie müssen sich in diesem Fall wahrscheinlich nicht allzu viele Gedanken über Formatierungsprobleme machen, da es sich nur um eine schnelle Überprüfung handelt.

Die Art von automatisiertem Ansatz

Wenn Sie wissen, dass es eine Weile dauern wird, aber so etwas wie eine Fortschrittsanzeige wollen, wäre eine Alternative, Ihren tar-Prozess zu starten und in einem anderen Terminal seine PID zu ermitteln und diese dann in ein Skript zu werfen, das einfach wiederholt ein Signal sendet. Wenn Sie zum Beispiel das folgende Skriptlet haben (und es als script.sh PID-to-signal interval-to-signal-at aufrufen):

#!/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?"

Wenn Sie es auf diese Weise aufrufen, erhalten Sie, da Sie nur auf tar abzielen, eher eine Ausgabe wie diese

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)
...

, was zugegebenermaßen ziemlich hübsch ist.

Zu guter Letzt - mein Skripting ist etwas eingerostet, wenn also jemand den Code aufräumen/verbessern möchte, nur zu :)

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

Inspiriert von Noah Spurriers Antwort

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
}

Quelle

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

Wenn Sie die Dateinummer statt der Gesamtgröße aller Dateien kennen:

Eine Alternative (weniger genau, aber geeignet) ist, die Option -l zu verwenden und in der Unix-Pipe die Dateinamen statt der Dateninhalte zu senden.

Wenn wir 12345 Dateien in mydir haben, lautet der Befehl:

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

Sie können diesen Wert im Voraus wissen (wegen Ihres Anwendungsfalls) oder einen Befehl wie find+wc verwenden, um ihn zu ermitteln:

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

Unter macOS stellen Sie zunächst sicher, dass Sie alle Befehle zur Verfügung haben, und installieren die fehlenden (z. B. pv) mit brew .

Wenn Sie nur tar ohne Komprimierung wollen, gehen Sie mit:

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

Wenn Sie komprimieren wollen, gehen Sie mit:

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

Hinweis: Es kann eine Weile dauern, bis der Fortschrittsbalken erscheint. Versuchen Sie es zuerst in einem kleineren Ordner, um sicherzustellen, dass es funktioniert, und wechseln Sie dann zu einem Ordner mit großen Dateien.

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

Methode basiert auf 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

Hier sind einige Zahlen einer Prometheus-Sicherung (Metrikdaten) auf Debian/Buster AMD64:

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

Dieser Auftrag wurde abgebrochen, da nicht genügend Plattenplatz verfügbar war.

Experimentieren mit zstd als Kompressor für tar mit Überwachung des Fortschritts mit 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

In meinem täglichen Gebrauch muss ich nicht den genauen prozentualen Fortschritt der Operation wissen, sondern nur, ob sie funktioniert und (manchmal) wie weit sie der Fertigstellung nahe ist.

Ich löse dieses Bedürfnis minimal, indem ich die Anzahl der verarbeiteten Dateien in einer eigenen Zeile anzeige; in der Bash:

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

Da ich das oft benutze, habe ich einen Funktionsalias in . bashrc:

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

Dann einfach:

tar zcvf files.tgz directory | pvl

Ich kann die Anzahl der Dateien im Voraus berechnen, wenn nötig mit find directory | wc -l (Oder besser mit der gleichen Funktion wie in [find directory | pvl], um meine Ungeduld zu zügeln!)

Ein anderes Beispiel, das Setzen von Rechten für eine virtuelle Website (danach ist ein chown -R schnell, weil die Dateinamen im Dateisystem-Cache sind):

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

Es stimmt, dass diese seitliche Verarbeitung die Hauptoperation verlangsamen könnte, aber ich denke, dass das Drucken eines Return-Zeichens und einiger Ziffern nicht zu teuer sein kann (abgesehen davon fühlt sich das Warten auf das nächste Gleichheitszeichen oder die Änderung der Prozentzahl langsam an, verglichen mit der subjektiv rasenden Geschwindigkeit der Ziffernänderung!)