Czy istnieje sposób, aby zobaczyć postęp postępu tar na plik?

122

Mam kilka dużych plików, które chciałbym skompresować. Mogę to zrobić na przykład

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

Problem polega na tym, że nie widzę żadnego postępu, więc nie mam pojęcia, ile to zajmie ani nic takiego. Używając v, mogę przynajmniej zobaczyć, kiedy każdy plik jest ukończony, ale gdy plików jest niewiele i jest to duże, nie jest to najbardziej pomocne.

Czy istnieje sposób, aby uzyskać tar, aby pokazać bardziej szczegółowe postępy? Na przykład procent ukończenia, pasek postępu lub szacowany pozostały czas lub coś w tym rodzaju. Dla każdego pojedynczego pliku lub wszystkich lub obu.

Svish
źródło

Odpowiedzi:

100

Wolę onelinerów takich jak ten:

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

Będzie miał taki wynik:

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

Dla OSX (z odpowiedzi 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
suma kontrolna
źródło
2
W systemie OSX du nie przyjmuje argumentu -b, musiał wrócić do: $ ((du -sk / folder-with | awk '{print $ 1}') * 1024))
29ɾɾǝʞ
4
Fajny, jeden liniowiec. Możesz to wyjaśnić? Czy może po prostu działa jakoś magicznie?
Kissaki,
2
Ok, mam topv $FILE.tgz | tar xzf - -C $DEST_DIR
Krzysztof Szewczyk
1
W przypadku OS X musiałem użyć nawiasu kwadratowego do rozszerzenia arytmetycznego, co sprawiło, że: tar cf - /folder-with-big-files -P | pv -s $[$(du -sk /folder-with-big-files | awk '{print $1}') * 1024] | gzip > big-files.tar.gzBez tej zmiany dostawałem-bash: syntax error near unexpected token ')'
Dean Becker
1
Zauważ, że postęp nie jest wyświetlany, dopóki polecenie du nie zakończy się, co może chwilę potrwać w zależności od rozmiaru, złożoności i fragmentacji katalogu.
Rooster242
75

Możesz to zrobić za pomocą pv . Aby poprawnie zgłosić postęp, pvmusisz wiedzieć, ile bajtów na niego rzucasz. Pierwszym krokiem jest więc obliczenie wielkości (w kilobajtach). Możesz także całkowicie upuścić pasek postępu i po prostu pvpowiedzieć ci, ile bajtów widział; zgłosiłoby „zrobione tyle i tak szybko”.

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

I wtedy:

% tar cvf - folder-with-big-files | pv -p -s ${SIZE}k | \ 
     bzip2 -c > big-files.tar.bz2
akira
źródło
Chłodny. pvwydaje się, że nie jest dostarczany z Mac OS X, ale wypróbuje to, gdy będę mieć komputer z MacPorts. Czy mógłbyś jednak wyjaśnić, co tam robisz? Nie jestem pewien, co dokładnie robi pierwsza linia.
Svish
4
pierwszy wiersz: pobierz informacje o tym, ile bajtów zostanie obsłużonych. druga linia: użyj rozmiaru z pierwszej linii, aby pozwolić pv na renderowanie „postępu”. ponieważ przesyłasz dane, pv nie wie, ile jeszcze bajtów nadejdzie.
akira
Jeden dodatek: SIZE=$(($SIZE * 1000 / 1024))- Nie wiem, czy to dziwactwo na mojej konkretnej platformie, więc nie dodam go do odpowiedzi: duzwraca rozmiar, w którym 1 kb = 1024 bajty, podczas gdy pvwydaje się, że oczekuje 1 kb = 1000 bajty. (Jestem na Ubuntu 10.04)
Izkata,
2
@lzkata zawsze możesz poprosić duo użycie preferowanego rozmiaru bloku, np. du -s --block-size=1000lub po prostu pracować z zwykłymi bajtami, np. upuścić pliki kz wywołań dui pv. Mimo to, chciałbym oczekiwać zarówno w użyciu 1024, chyba powiedziano inaczej, np --siwłączeniu du, na przykład.
Legolas
1
lub po prostu upuść k-stuff i po prostu użyj zwykłych bajtów ( du -sbi pv -sbez żadnego modyfikatora). to powinno zakończyć wszystkie zamieszanie.
akira
22

lepszy pasek postępu ..

apt-get install pv dialog

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

wprowadź opis zdjęcia tutaj

Pan Black
źródło
2
Działa to do rozpakowywania, ale nadal musisz wykonać jedno z bardziej skomplikowanych poleceń tworzenia (co było pierwotnym pytaniem). Nadal można go łączyć z tymi; to po prostu bardziej skomplikowane.
Daniel H
17

Sprawdź opcje --checkpointi --checkpoint-actionna stronie informacji o tar (tak jak w przypadku mojej dystrybucji opis tych opcji nie jest zawarty na stronie podręcznika → RTFI).

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

Za pomocą tych (i być może funkcji napisania własnego polecenia punktu kontrolnego) możesz obliczyć procent…

pomocnik
źródło
3
To powinna być poprawna odpowiedź. Inni po prostu wyjaśniają dodatkowe narzędzia (poza tym domyślnie nie instalowane), aby osiągnąć coś podobnego.
Carmine Giangregorio
@Sardathrion Może dlatego, że jest tarspecyficzny dla GNU .
phk
11

Zainspirowany odpowiedzią pomocnika

Innym sposobem jest użycie taropcji natywnych

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

wynik jest jak

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

kompletny przykład tutaj

Campisano
źródło
4

Używanie tylko smoły

tarma opcję (od wersji 1.11) do drukowania informacji o statusie sygnałów za pomocą --totals=$SIGNOnp .:

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

Total bytes written: [...]Informacja zostanie wydrukowany na każdym sygnale USR1, np:

pkill -SIGUSR1 tar

Źródło:

Murmel
źródło
3

Właśnie zauważyłem komentarz na temat MacOS i chociaż myślę, że rozwiązanie z @akira (i pv) jest znacznie fajniejsze, pomyślałem, że ścigam przeczucie i szybkie zagranie w moim MacOS z tar i wysyłając mu sygnał SIGINFO. Co zabawne, zadziałało :) jeśli korzystasz z systemu podobnego do BSD, powinno to działać, ale na Linux-ie może być konieczne wysłanie SIGUSR1 i / lub tarmoże nie działać w ten sam sposób.

Wadą jest to, że zapewni ci tylko wyjście (na standardowym wyjściu) pokazujące, jak daleko jest do bieżącego pliku, ponieważ domyślam się, że nie ma pojęcia o tym, jak duży jest strumień danych.

Tak więc, alternatywnym podejściem byłoby odpalenie tar i okresowe wysyłanie jej SIGINFO w dowolnym momencie, aby dowiedzieć się, jak daleko się zaszła. Jak to zrobić?

Podejście ad hoc, ręczne

Jeśli chcesz mieć możliwość sprawdzania statusu na zasadzie ad hoc, możesz nacisnąć control-T(jak wspomniano Brian Swift) w odpowiednim oknie, które prześle sygnał SIGINFO. Jednym z problemów jest to, że przesyła to do całego łańcucha, wierzę, więc jeśli robisz:

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

Zobaczysz także raport bzip2 o jego statusie wraz z 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)

Działa to dobrze, jeśli chcesz po prostu sprawdzić, tarczy Twój bieg jest zablokowany lub po prostu wolny. W tym przypadku prawdopodobnie nie musisz się zbytnio przejmować problemami z formatowaniem, ponieważ jest to tylko szybkie sprawdzenie ...

Rodzaj zautomatyzowanego podejścia

Jeśli wiesz, że zajmie to trochę czasu, ale potrzebujesz czegoś w rodzaju wskaźnika postępu, alternatywą byłoby odpalenie procesu tar, a na innym terminalu ustalenie jego PID, a następnie wrzucenie go do skryptu, który po prostu wielokrotnie wysyła sygnał . Na przykład, jeśli masz następujący skryptlet (i wywołujesz go jak powiedzmy 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?"

Jeśli wywołasz to w ten sposób, ponieważ celujesz tylko tar, uzyskasz bardziej podobny wynik

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

co przyznaję, jest dość ładne.

Last but not least - moje skrypty są trochę zardzewiałe, więc jeśli ktoś chce wejść i wyczyścić / naprawić / poprawić kod, idź po swoje życie :)

tanantish
źródło
2
Jeśli uruchomione tarw wierszu poleceń, wpisanie control-Twyśle ​​mu SIGINFO. Gdyby to było w skrypcie, byłoby to zrobione zkill -INFO pid
Brian Swift,
Zupełnie zapomniałem control-T, najwyraźniej przyzwyczaiłem się do spamowania zbyt wieloma oknami konsoli dla własnego dobra.
tanantish
1
dlaczego nie widzę -SIGINFO podczas robieniakill -l
Felipe Alvarez
2

Zainspirowany odpowiedzią 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
}

Źródło

Steven Penny
źródło
17
Może mały kontekst i wyjaśnienie?
Kissaki,
1

Jeśli znasz numer pliku zamiast całkowitego rozmiaru wszystkich:

alternatywą (mniej dokładne, ale odpowiednie) jest użycie opcji -l i przesłanie w potoku unix nazw plików zamiast zawartości danych.

Miejmy 12345 plików w moim katalogu , polecenie to:

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

możesz znać taką wartość z góry (ze względu na swój przypadek użycia) lub użyć polecenia, np. find + wc, aby ją odkryć:

[myhost@myuser mydir]$ find | wc -l
12345
bzimage
źródło
Dlaczego więc nie umieścić tego polecenia w podkomendie? =)
Kirby,
tar cfvz ~/mytarfile.tgz . | pv -s $(find . | wc -l) -l > /dev/null. Czy Ci to pasuje?
Kirby
1

Metoda oparta na tqdm :

tar -v -xf tarfile.tar -C TARGET_DIR | tqdm --total $(tar -tvf tarfile.tar | wc -l) > /dev/null
J_Zar
źródło
1

W systemie macOS najpierw upewnij się, że masz wszystkie dostępne polecenia i zainstaluj brakujące (np. pv) Za pomocą brew .

Jeśli chcesz tylko tar bez kompresji , skorzystaj z:

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

Jeśli chcesz skompresować , skorzystaj z:

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

Uwaga: zanim pojawi się pasek postępu, może minąć trochę czasu. Wypróbuj najpierw mniejszy folder, aby upewnić się, że działa, a następnie przejdź do folderu z dużymi plikami.

Królik Bugs
źródło
0

Oto kilka kopii zapasowych prometheus (dane metryk) na Debian / buster AMD64:

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

Anulowano to zadanie, ponieważ nie było wystarczającej ilości miejsca na dysku.

Eksperymentowanie z zstdkompresorem do tarmonitorowania postępu za pomocą 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
dylematy
źródło