lista de arquivos tar, quebra no primeiro arquivo

1

Eu tenho usado o snippet a seguir extraído de um post semelhante - link - para obter um nome de arquivo de um tar.gz file:

tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }'

Para o meu caso, eu só preciso de um arquivo específico, então eu uso algo como:

tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' | grep -e "^..*my-file-name\.ext$"

A parte principal é que meu .tar.gz é muito grande e contém muitos arquivos. No entanto, cada um tem um "hash" similar anexado ao início (daí a ^..* parte do meu grep'd regex).

Assim, os arquivos podem parecer:

- 4b77e4e1_file-a.ext
- 4b77e4e1_file-b.ext
- 4b77e4e1_file-c.ext
# ect.

Notei que o comando para obter todos os arquivos ( tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' ) transmite a saída.

Meu pensamento é, se eu pudesse "quebrar" o fluxo, em seguida, extrair essa primeira parte hash, eu poderia construir meu nome de arquivo que eu eventualmente precisava sem ter que percorrer todo o conteúdo do arquivo .tar.gz . / p>

Então, minha pergunta é, como eu posso "quebrar" awk em sua primeira saída, ao invés de esperar que o comando inteiro termine (o que leva vários minutos) e usar o resultado para obter o nome do arquivo. eventualmente quer .

EDIT : Parece que eu quero quebrar tar , como simplesmente exit ing após o primeiro resultado não alterar o tempo de execução.

    
por romellem 22.02.2017 / 16:27

3 respostas

2

tente algo como

 tar tzf "archive.tar.gz" | awk -F/ '$NF ~ /my-filename$/ {print $NF ; exit }'

ou

 tar tzf "archive.tar.gz" | awk -F/ 'substr($NF,4,11) == "my-filename" {print $NF ; exit }'

(onde 4 e 11 devem corresponder ao nome do arquivo real).

    
por 22.02.2017 / 16:38
2

Você pode dizer ao AWK para sair depois de imprimir algo:

awk -F/ '$NF != "" { print $NF; exit }'

Como você está procurando por um nome de arquivo específico:

awk -F/ '/my-file-name\.ext$/ && $NF != "" { print $NF; exit }'

O teste $NF é redundante, então:

awk -F/ '/my-file-name\.ext$/ { print $NF; exit }'
    
por 22.02.2017 / 16:34
1

Se um dos programas no pipeline sair, os programas à esquerda também serão encerrados. A maneira como isso funciona é:

  • Em foo | bar , bar sai.
  • A saída do processo fecha a extremidade de leitura do canal.
  • Quando foo tenta gravar no pipe, ele recebe um sinal SIGPIPE.
  • foo morre.

Isso pressupõe que foo não tenha protegido contra o SIGPIPE; programas podem fazer isso, mas programas típicos de linha de comando não.

Como você deseja apenas uma correspondência, faça o awk sair assim que encontrar a linha em que está interessado:

tar tzf "archive.tar.gz" | awk -F/ '$NF ~ /.my-file-name\.ext$/ {print $NF; exit}'

ou (não é realmente vantajoso aqui)

tar tzf "archive.tar.gz" | sed -n '/[^/]my-file-name\.ext$/ {s!.*/!!; q}'

ou, continuando com sua abordagem mais complicada de usar o grep separadamente do awk

tar tzf "archive.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' | grep -e "^..*my-file-name\.ext$" | head -n 1

Sair do leitor faz com que tar seja encerrado quando ele for gravado no canal, o que pode demorar um pouco, devido a buffer de saída . (Levará um tempo especialmente longo se houver mais de dois processos no pipe, pois haverá algum atraso para cada um receber SIGPIPE.) Depois que awk sair, find gastará um pouco lendo o arquivo e preenchendo o próximo buffer com os nomes dos arquivos, e finalmente tente gravar o buffer e morrer com o SIGPIPE. Para este aplicativo, é muito provável que seja mais rápido alternar o tar para o buffer de linha para saída, o que você pode fazer com stdbuf :

stdbuf -oL tar tzf "archive.tar.gz" | awk -F/ '$NF ~ /.my-file-name\.ext$/ {print $NF; exit}'

Alternativamente, você pode organizar o kill do programa tar quando o awk sair, mas isso é mais complicado.

sh -m 'tar tzf "archive.tar.gz" | {
         awk -F/ "$0";
         kill -TERM -$$;
       }' '$NF ~ /.my-file-name\.ext$/ {print $NF; exit}'
[ $? -eq 143 ]
    
por 23.02.2017 / 00:48

Tags