Search for a file inside a tar.gz file without extracting it and copy the result to another folder

tar

I need to search for a file inside a tar.gz file without extracting it. After that, I need to copy the file that was searched (if ever there is) to another folder.

So far I have this, but the copy part of this line gives me an error.

gunzip -c file.tar.gz | tar tvf - | grep filename | -exec cp {} /folder/another_folder \;

Or is there a better way to search for a file inside a tar.gz file without extracting it?

Best Answer

Does your version of tar not support the switch -z?

$ tar ztvf file.tar.gz | grep fliename

This would then return the name of the file if it existed at all in the archive.

Extracting the file

You could do something like this if you wanted to search for the file first, and only if present then extract it.

$ arc="<tarball>"; file="<file to extract>"; \
        tar ztvf $arc | grep $file && tar zxvf $arc $file

Sample Tarball

$ tar ztvf ffmpeg.static.64bit.2013-10-05.tar.gz 
-rwxr-xr-x root/root  19579304 2013-10-05 00:06 ffmpeg
-rwxr-xr-x root/root  19528712 2013-10-05 00:06 ffprobe

Example

$ arc="ffmpeg.static.64bit.2013-10-05.tar.gz"; file="ffmpeg"; \
       tar ztvf $arc | grep $file && tar zxvf $arc $file

-rwxr-xr-x root/root  19579304 2013-10-05 00:06 ffmpeg
ffmpeg

Confirmation

$ ll ffmpeg
-rwxr-xr-x 1 manny manny 19579304 Oct  5 00:06 ffmpeg*

A different directory

If you want to output the extracted file to some other location you can use tar's -C switch.

$ arc="<tarball>"; file="<file to extract>"; \
        tar ztvf $arc | grep $file && tar zxvf $arc -C /path/to/dir $file

Example #1

$ arc="ffmpeg.static.64bit.2013-10-05.tar.gz"; \
       file="ffmpeg"; tar ztvf $arc | grep $file && tar zxvf $arc -C /tmp $file

Confirmation

$ ll /tmp/ffmpeg
-rwxr-xr-x 1 manny manny 19579304 Oct  5 00:06 /tmp/ffmpeg*

Example #2

$ arc=cp210x.tar.gz; file="cp210x/usb-serial/Makefile"; \
       tar ztvf $arc | grep $file && tar zxvf $arc -C /tmp $file

Confirmation

$ ll /tmp/cp210x/usb-serial/Makefile 
-rw-rw-r-- 1 manny manny 388 May 13 01:37 /tmp/cp210x/usb-serial/Makefile

Example #3

Wildcards could also be used if you want to extract a pattern of files.

$ arc=cp210x.tar.gz; file='*Makefile'; \
       tar ztvf $arc | grep -E "$file" && tar zxvf $arc -C /tmp --wildcards "$file"

Confirmation

$ find /tmp/cp210x -ls | grep Makefile
26881948    4 -r--r--r--   1 manny    manny         171 Mar 14  2012 /tmp/cp210x/Linux_3.x.x_VCP_Driver_Source/Makefile
26881960    4 -rw-rw-r--   1 manny    manny         388 May 13 01:37 /tmp/cp210x/usb-serial/Makefile

Details

The above involves a couple of additional changes. We're extracting everything that matches '*Makefile'. Notice that we've wrapped it in single quotes vs. double quotes now. This is to protect the *Makefile from getting accidentally expanded.

grep now includes the switch -E, because we're searching for a regular expression now and not just a single string within the output of tar. Also the argument to grep is also not wrapped in double quotes.

We now use the switch --wildcards to the 2nd tar so that we can extract based on a pattern rather than just a single file. This argument too is now wrapped in double quotes to protect it.

Related Question