Procura por um arquivo dentro de um arquivo tar.gz sem extraí-lo e copia o resultado para outra pasta

5

Eu preciso procurar um arquivo dentro de um arquivo tar.gz sem extraí-lo. Depois disso, preciso copiar o arquivo que foi pesquisado (se houver) para outra pasta.

Até agora eu tenho isso, mas a parte da cópia dessa linha me dá um erro.

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

Ou existe uma maneira melhor de procurar um arquivo dentro de um arquivo tar.gz sem extraí-lo?

    
por kickass13 17.10.2013 / 03:42

2 respostas

8

A sua versão de tar não suporta o parâmetro -z ?

$ tar ztvf file.tar.gz | grep fliename

Isso retornaria o nome do arquivo se ele existisse no arquivo.

Extraindo o arquivo

Você poderia fazer algo assim se quisesse procurar o arquivo primeiro e apenas se presente, depois extraí-lo.

$ 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

Exemplo

$ 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

Confirmação

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

Um diretório diferente

Se você quiser enviar o arquivo extraído para outro local, use a opção tar -C .

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

Exemplo # 1

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

Confirmação

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

Exemplo # 2

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

Confirmação

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

Exemplo # 3

Caracteres curinga também podem ser usados se você quiser extrair um padrão de arquivos.

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

Confirmação

$ 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

Detalhes

O acima envolve algumas alterações adicionais. Estamos extraindo tudo o que corresponde a '*Makefile' . Observe que nós o incluímos em aspas simples versus aspas duplas agora. Isso é para proteger o *Makefile de ser expandido acidentalmente.

grep agora inclui a opção -E , porque estamos procurando uma expressão regular agora e não apenas uma única string na saída de tar . Além disso, o argumento para grep também não está entre aspas duplas.

Agora usamos o switch --wildcards para o segundo tar , para que possamos extrair com base em um padrão, em vez de apenas um único arquivo. Este argumento também está agora entre aspas duplas para protegê-lo.

    
por 17.10.2013 / 04:01
1

Você não pode fazer isso em um passo, receio. Você não pode (facilmente) extrair parte de um arquivo para um local diferente do que foi arquivado. Você provavelmente pode fazer algo assim:

pattern=filename
file_path="$(tar tzf file.tar.gz 2>/dev/null| grep "$pattern")"
if [ ! -n "$file_path ];then
    tar xvzf file.tar.gz "$file_path"
    cp "$file_path" /new/location
else
    echo "No files matching $pattern found in archive"
fi

Agora, para essa observação "fácil" acima. A implementação GNU de tar tem uma opção --strip-components que recebe um número e retira muitos componentes do nome do arquivo antes da extração. Assim, você pode contar quantos componentes existem antes do nome da base, para que você possa fazer uma espécie de operação de "extrair aqui", seguida de uma cópia:

pattern=filename
file_path="$(tar tzf file.tar.gz | grep "$pattern" )"
file_name="$(basename "$file_path")"
[ -z "$file_path" ] && echo "No files matching $pattern found." && exit 1
components=0
while [ "$file_path" != '/' ];do
    file_path=$(dirname "$file_path")
    components=$((components+1))
done
tar xvzf file.tar.gz --strip-components "$components" "$file_path" && cp "$file_name" /new/location
    
por 17.10.2013 / 04:01

Tags