有没有办法查看每个文件的tar进度?


122

我有几个要压缩的大文件。我可以用例如

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

问题是我看不到任何进展,所以我不知道需要多长时间或类似的事情。使用vI至少可以看到每个文件何时完成,但是当文件很少又很大时,这并不是最有用的。

有没有办法让tar显示更详细的进度?就像完成百分比或进度条或估计的剩余时间之类的。对于每个单个文件或全部或两个。

Answers:


100

我更喜欢这样的单人纸:

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

它将具有以下输出:

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

对于OSX(根据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

2
在OSX上,du不带-b参数,需要回退至:$((du -sk / folder-with | awk'{print $ 1}')* 1024))
ı13uǝʞ2013年

4
不错,一个班轮。你能解释一下吗?还是以某种方式神奇地起作用?
Kissaki 2014年

2
好的,我知道了pv $FILE.tgz | tar xzf - -C $DEST_DIR
Krzysztof Szewczyk

1
对于OS X,我需要使用方括号形式进行算术扩展,这使得:tar cf - /folder-with-big-files -P | pv -s $[$(du -sk /folder-with-big-files | awk '{print $1}') * 1024] | gzip > big-files.tar.gz如果没有此更改,我将会-bash: syntax error near unexpected token ')'
Dean Becker 2015年

1
请注意,直到du命令完成才显示进度,这可能需要一段时间,具体取决于目录的大小,复杂性和碎片。
Rooster242

75

您可以使用pv实现此目的。要正确报告进度,pv需要知道您要向其扔多少字节。因此,第一步是计算大小(以KB为单位)。您也可以完全删除进度条,只pv告诉您它已看到多少字节。它会报告“做得那么快”。

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

接着:

% tar cvf - folder-with-big-files | pv -p -s ${SIZE}k | \ 
     bzip2 -c > big-files.tar.bz2

凉。pv似乎不是Mac OS X附带的,但是一旦我有一台装有MacPorts的计算机,就可以尝试一下。你能解释一下你在做什么吗?不太清楚第一行到底是做什么的。
Svish

4
第一行:获取有关将要处理的字节数的信息。第二行:使用第一行的大小来允许pv渲染“进度”。由于正在传递数据,因此pv不知道还会有多少字节。
akira

一个补充:SIZE=$(($SIZE * 1000 / 1024))-我不知道这在我的特定平台上是否是一个怪癖,因此我没有将其添加到答案中: du返回大小,其中1 kb = 1024字节,而pv似乎期望1 kb = 1000个字节。(我在Ubuntu 10.04上)
Izkata 2011年

2
@lzkata您总是可以要求du使用您喜欢的块大小,例如du -s --block-size=1000,或者只使用纯字节,例如kdupv调用中删除。不过,1024除非另有说明,否则我希望两者都可以使用,例如,--si打开du
Legolas 2012年

1
或只是下降的k的东西,只是使用纯字节(du -sbpv -s无任何改性剂)。那应该结束所有的混乱。
akira 2012年

22

更好的进度条

apt-get install pv dialog

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

在此处输入图片说明


2
这适用于提取,但是您仍然需要执行更复杂的命令之一来创建(这是原始问题)。它仍然可以与那些结合起来;这只是更复杂。
Daniel H

17

在tar信息页面中查看--checkpoint--checkpoint-action选项(就我的分布而言,手册页→RTFI中未包含这些选项的描述)。

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

有了这些(也许还有编写自己的checkpoint命令的功能),您可以计算百分比…


3
这应该是正确的答案。其他人只是解释了一些额外的工具(默认情况下未安装)以实现类似目的。
胭脂红Giangregorio

@Sardathrion也许是因为它是GNU tar特定的。
phk

11

受到助手回答的启发

另一种方法是使用本机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 "]"

结果就像

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

一个完整的例子在这里


4

仅使用tar

tar可以选择(自v1.12起)使用来在信号上打印状态信息--totals=$SIGNO,例如:

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

Total bytes written: [...]信息会打印在每个USR1信号上,例如:

pkill -SIGUSR1 tar

资源:


3

刚刚注意到了有关MacOS的评论,虽然我认为@akira(和pv)的解决方案更加整洁,但我想我会在我的MacOS盒中使用tar并向其发送SIGINFO信号来寻找预感和快速解决方法。有趣的是,它可以工作:)如果您使用的是类似BSD的系统,则应该可以,但是在Linux机器上,您可能需要发送SIGUSR1,并且/或者tar可能无法以相同的方式工作。

不利的一面是,它将仅向您提供一个输出(在stdout上),该输出向您显示该文件在当前文件中的距离,因为我猜测它不知道它所获取的数据流的大小。

因此,是的,另一种方法是启动tar,并在您想知道它走多远时定期发送SIGINFO。这个怎么做?

临时的手动方法

如果您希望能够临时检查状态,则可以control-T在相关窗口中单击(如Brian Swift所述),该窗口将发送SIGINFO信号。我认为,与此相关的一个问题是它将其发送到您的整个链中,因此,如果您这样做:

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

您还将看到bzip2和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)

如果您只想检查tar您的跑步机是否卡住,或者速度很慢,则此方法效果很好。在这种情况下,您可能不必太担心格式问题,因为这只是快速检查。

那种自动化的方法

如果您知道这将需要一段时间,但是想要一个进度指示器之类的方法,则可以启动tar进程,然后在另一个终端中计算出它的PID,然后将其放入脚本中,该脚本反复发送信号。例如,如果您具有以下脚本(并像说那样调用它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?"

如果以这种方式调用它,则由于仅定位,因此tar您将获得类似以下的输出

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

我承认,这很漂亮。

最后但并非最不重要的一点-我的脚本有点生锈,因此,如果有人想进入并清理/修复/改进代码,请毕生:)


2
如果tar在命令行上运行,则键入control-T将向其发送SIGINFO。如果在脚本中执行此操作,则可以使用kill -INFO pid
Brian Swift 2012年

完全忘了control-T,我明明已经习惯了垃圾邮件太多控制台窗口为我自己好..
tanantish

1
为什么在执行时看不到-SIGINFOkill -l
Felipe Alvarez

2

受到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
}

资源


17
可能有一点背景和解释?
Kissaki 2014年

1

如果您知道文件号而不是全部文件的总大小:

另一种方法(准确性较差但不适合使用)是使用-l选项,并在Unix管道中发送文件名而不是数据内容。

让我们将12345个文件放入mydir,命令是:

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

您可以事先知道这样的值(因为您的用例),或者使用诸如find + wc之类的命令来发现它:

[myhost@myuser mydir]$ find | wc -l
12345

那么,为什么不将此命令放入子命令呢?=)
柯比(Kirby

tar cfvz ~/mytarfile.tgz . | pv -s $(find . | wc -l) -l > /dev/null。对你起作用吗?
柯比

1

基于tqdm的方法:

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

1

macOS上,首先确保您具有所有可用的命令,然后pv使用brew安装缺少的命令(例如)。

如果只想tar 不压缩,请使用:

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

如果要压缩,请继续:

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

注意:可能需要一段时间才能显示进度条。首先尝试在较小的文件夹上进行确认,然后再移至“大文件文件夹”。


0

以下是Debian / buster AMD64上的一些普罗米修斯(指标数据)备份:

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

由于没有足够的磁盘空间,取消了此作业。

zstd作为压缩器进行试验,以tar使用以下命令监视进度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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.