38

I'd like to print at the very least print # files extracted, from running a tarball extract

xz -dc /path/to/somearchive.tar.xz | sudo tar xvpf - -C /path/to/some_directory

I was thinking of using the "\r" as mentioned in this question, for instance

num=0
when [\n received]
    num=$(($num + 1))
    echo -ne "$num files extracted \r"
end when

my bash skills fail me.

6 Answers 6

77

Using pv to pipe the file to tar.

  1. Firstly, you'll need to install pv, which on macOS can be done with:

    brew install pv
    

    On Debian or Ubuntu, it can be done with: apt install pv (Thanks @hyperbola!).

  2. Pipe the compressed file with pv to the tar command:

    pv mysql.tar.gz | tar -xz   
    

Here's the sample output of this command:

Sample output

For those curious, this works by pv knowing the total file size of the file you pass it and how much of it has been "piped" to the tar command. It uses those two things to determine the current progress, the average speed, and the estimated completion time. Neat!

4
  • 3
    pv "$SOURCE_FILE" | xz -0 --stdout > "$TARGET_FILE", in case someone is trying to 'zip' using xz. Yes, it's the opposite of what OP is doing, but that's what I was looking for :) Commented Jan 25, 2022 at 17:58
  • Can it be done with additional -v parameter for tar?
    – alper
    Commented Apr 7, 2022 at 11:26
  • 1
    For debian or ubuntu users, pv can be installed by apt install pv.
    – hyperbola
    Commented Sep 20, 2022 at 3:04
  • @hyperbola Thank you for adding that. I've added it to the answer as well. Commented Sep 20, 2022 at 16:04
50

When extracting with tar you can use the --checkpoint option. What you get is not really a progress bar but good enough to see the progress.

In this example, tar will print a message each 100 records written. If you place a dot immediately after the equal sign, it will just print a ..

tar -xf somearchive.tar.gz --checkpoint=.100

Output:

.......
4
  • This should be the accepted answer, simple yet useful +1.
    – gorjan
    Commented Jun 17, 2021 at 0:02
  • This just shows ... without its 100% percent
    – alper
    Commented Nov 17, 2021 at 10:47
  • 3
    This doesn't seem to work on centos release 8 with gnu tar v1.30. What works on gnu tar is: tar xvnf archive.tgz --checkpoint=1000 --checkpoint-action=dot. This was introduced in v1.20
    – akhan
    Commented May 23, 2022 at 17:49
  • 1
    Per @royarisse's answer, we can make tar to print 1 dot for roughly 1% by adjusting the checkpoint size, e.g. in bash tar -xf somearchive.tar.gz --checkpoint=$(($(stat -c %s somearchive.tar.gz)/512/20/100)) --checkpoint-action=.
    – Lacek
    Commented Mar 23, 2023 at 15:21
14

If you really want to do it by file you could use:

tar xvpf /path/to/archive.tar.xz -C /path/to/dir 2>&1 | 
while read line; do
    x=$((x+1))
    echo -en "$x extracted\r"
done

Notes:

  • You probably don't need to xz separately, most tar implementations will automatically detect and decompress it for you.
  • tar reads from stdin by default, you don't need f -.

You should look into using pv instead, it's more precise and more generally applicable:

pv /path/to/archive.tar.xz | tar xp -C /path/to/dir
8
  • You forgot xzcat in your pv sample: pv /path/to/archive.tar.xz | xzcat | sudo tar -xpC /path/to/dir Commented Oct 15, 2013 at 2:57
  • Nice answer, didn't know that tar output could be sequentially piped like that
    – higuaro
    Commented Oct 15, 2013 at 2:59
  • @F.Hauri no I'm not, see my note about tar automatically detecting compression.
    – Kevin
    Commented Oct 15, 2013 at 3:00
  • 1
    With pv, then, per file: lines=$(tar -tJf archive.txz | wc -l); tar -xvpf archive.txz 2>&1 | pv -ls$lines
    – kojiro
    Commented Oct 15, 2013 at 3:11
  • 1
    this: pv /path/to/archive.tar.xz | sudo tar xp -C /path/to/dir how could I make it an alias, so I could write something like: progtar inputfile destination/dir Commented Jan 1, 2016 at 18:07
6

While the pv solution shows progress nicely, it doesn't show what files are extracted whereto. The --checkpoint=.100 option shows the files and indicates that it's working, but doesn't show progress.

On the Tar Checkpoints page I found some information about the --checkpoint-action option, which is able to execute some bash magic for every checkpoint. Knowing that a checkpoint is created every 20 blocks of 512 bytes (at least that's the default, see man tar), It's possible to get the progress based on the current block and the original size.

The snippet below can be saved as a bash file (or put into a bash function):

archive="$1"

originalsize=$(file $archive | rev | cut -d' ' -f1 | rev)
step=100
blocks=$(echo "$originalsize / 512 / 20 / $step" | bc)

tar -xvz --checkpoint=$step --totals \
 --checkpoint-action="exec='p=\$(echo "\$TAR_CHECKPOINT/$blocks" | bc -l);printf \"%.4f%%\r\" \$p'" \
 -f $archive

Then using it is very straightforward:

bash tarprogress.sh your.archive.tgz
2

You can do this with xz files like this:

unxz -v --stdout file.tar.xz | tar -x
1

There's also progress, which you could use like this:

tar xp -C /path/to/dir & progress -mp $!

Or even:

watch progress -q

Not the answer you're looking for? Browse other questions tagged or ask your own question.