How can I extract files from a .tar.gz archive while keeping a trace of the extracted files?

For example, let's say I have the following file structure...

 ╠═▶ children
 ║    ╠═▶ joe.txt
 ║    ╚═▶ george.txt
 ╠═▶ bar.txt
 ╠═▶ foo.txt
 ╚═▶ A̲R̲C̲H̲I̲V̲E̲.t̲a̲r̲.b̲z̲
      ├─▷ children
      │    ├─▷ joe.txt
      │    └─▷ bob.txt
      ├─▷ hello.txt
      ├─▷ world.txt
      └─▷ foo.txt

Now, if I extract the files from the archive while keeping the newer files in place I'd like to know which ones have been extracted so I can do something like this:
tar xf ./ARCHIVE.tar.gz --keep-newer-files | xargs -I EXTRACTED_FILE echo EXTRACTED_FILE


I will use the option --to-command to trigger the print of all extracted files

the argument is a command that will use the env variable TAR_FILENAME to have the file name , and will receive thee file on STDIN

So you must read STDIN and create the extracted file , you can print on STDOUT the file you created

tar -xzf ../ARCH.tgz --keep-newer-files \
   --to-command="sh -c $(printf '%q' \
  'mkdir -p "$(dirname "$TAR_FILENAME")";dd of="$TAR_FILENAME" >/dev/null 2>&1;echo "#EXTRACTED#$TAR_FILENAME" ')" > output_tar.txt

and in output_tar.txt you will have a line for each extracted file .

see https://www.gnu.org/software/tar/manual/html_node/Writing-to-an-External-Program.html

  • I tried it and I thought it worked for a second but I realized output_tar.txt contains the list of files that would be extracted has expected but nothing is extracted from the archive.It does not extract the files.
    – Elie G.
    Oct 9 '19 at 14:31
  • This why in my example , the command has 2 parts . one part for a dd command , and one part to echo the filename Oct 9 '19 at 16:27
  • Sorry, maybe I'm dumb but I don't understand. I tried to redirect stderr of dd into a file and it says dd: failed to open 'file/in/archive.txt': No such file or directory for every file that should be extracted
    – Elie G.
    Oct 9 '19 at 16:34
  • I managed to fix this issue by making sure the file pre-existed before calling dd. Here is the command I used for the --to-command argument of tar: sh -c $(printf '%q' 'mkdir -p $(dirname $TAR_FILENAME) ; touch $TAR_FILENAME ; dd of="$TAR_FILENAME" >/dev/null 2>&1 ; echo "#EXTRACTED#$TAR_FILENAME" ')
    – Elie G.
    Oct 9 '19 at 16:55

Depending of my requirement, I sometimes need to list all available extracted files matching the archive content (whether or not newer).

In that case, I can list the files effectively extracted, once the tar extraction was performed (or not).

I do it like this:

tar -xzf ./ARCH.tgz --keep-newer-files
for file in $(tar -tf ./ARCH.tgz 2>/dev/null)
  if [[ -e $file && ! -d $file ]]
    echo $file
done > output_tar.txt

A maybe less explicit but concise solution using xargs is:

tar -tf ./ARCH.tar 2>/dev/null | xargs -L1 bash -c 'if [[ -e $0 && ! -d $0 ]]; then echo $0; fi;'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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