untar um diretório de arquivos * .tgz usando um curinga

3

Eu tenho um diretório que parece

$ ls
Broad_hapmap3_r2_Affy6_cels_excluded.tgz  DINGO.tgz                     GIGAS.tgz  index.html          IONIC.tgz             passing_cels_sample_map.txt  SCALE.tgz
CHEAP.tgz                                 EPODE.tgz                     HOMOS.tgz  index.html?C=M;O=A  LOVED.tgz             PICUL.tgz                    SHELF.tgz
CORER.tgz                                 excluded_cels_md5.txt         HUFFS.tgz  index.html?C=N;O=D  NIGHS.tgz             POSIT.tgz                    SLOTH.tgz
CUPID.tgz                                 excluded_cels_sample_map.txt  HUSKS.tgz  index.html?C=S;O=A  passing_cels_md5.txt  SAKES.tgz                    TESLA.tgz

Eu quero descompactar todos os arquivos que correspondem à extensão * .tgz com um único comando, exceto Broad_hapmap3_r2_Affy6_cels_excluded.tgz.

Eu posso fazer

ls *.tgz | xargs -n1 tar zxvf

para todos os arquivos * tgz, mas qual é uma boa maneira de excluir um subconjunto deles? De ler on-line talvez encontrar é indicado nesta situação, mas parece um exagero. Agradeço antecipadamente.

Adendo: também estaria interessado em métodos alternativos para a pergunta sem excluir arquivos.

    
por Faheem Mitha 16.02.2011 / 17:15

3 respostas

0

Você sempre pode fazer:

ls *.tgz | grep -v Broad_hapmap3_r2_Affy6_cels_excluded.tgz | xargs -n1 tar zxvf

Mas eu suspeito que alguém vai postar uma maneira mais limpa fazer isso diretamente do shell bash sem precisar de um grep lá.

    
por 16.02.2011 / 17:35
7

No zsh:

setopt extended_glob
for z in *.tgz~Broad_hapmap3_r2_Affy6_cels_excluded.tgz; do tar xzf $z; done

Outra possibilidade no zsh:

setopt extended_glob
zargs -n 1 -- *.tgz~Broad_hapmap3_r2_Affy6_cels_excluded.tgz -- tar xzf

Em ksh (mas não bash ou zsh, pois eles não suportam e padrões):

for z in @(*.tgz&!(Broad_hapmap3_r2_Affy6_cels_excluded.tgz); do tar xzf "$z"; done

Outra maneira no ksh:

( FIGNORE=Broad_hapmap3_r2_Affy6_cels_excluded.tgz;
  for z in *.tgz; do tar xzf "$z"; done )

No bash:

( GLOB_IGNORE=Broad_hapmap3_r2_Affy6_cels_excluded.tgz;
  for z in *.tgz; do tar xzf "$z"; done )

Em qualquer shell:

for z in *.tgz; do
  [ "$z" = Broad_hapmap3_r2_Affy6_cels_excluded.tgz ] || tar xzf "$z"
done

Mais uma outra maneira estranha:

mv Broad_hapmap3_r2_Affy6_cels_excluded.tgz Broad_hapmap3_r2_Affy6_cels_excluded.tgz.not
for z in *.tgz; do tar xzf "$z"; done
mv Broad_hapmap3_r2_Affy6_cels_excluded.tgz.not Broad_hapmap3_r2_Affy6_cels_excluded.tgz

Se você também quiser agir em arquivos em subdiretórios, o find é a ferramenta natural a ser usada. Os exemplos recursivos abaixo excluem arquivos denominados Broad_hapmap3_r2_Affy6_cels_excluded.tgz em qualquer subdiretório.

find . -name '*.tgz' -type f \
       \! -name Broad_hapmap3_r2_Affy6_cels_excluded.tgz \
       -exec tar xzf {} \;

Para uma travessia recursiva em zsh ou bash ≥4, você pode usar ** em padrões. Em zsh:

setopt extended_glob
zargs -n 1 -- **/*.tgz~**/Broad_hapmap3_r2_Affy6_cels_excluded.tgz -- tar xzf

Em bash ≥4:

shopt -s globstar
( GLOB_IGNORE=Broad_hapmap3_r2_Affy6_cels_excluded.tgz;
  for z in **/*.tgz; do tar xzf "$z"; done )

Você pode até mesmo encontrar se não quiser uma travessia recursiva, embora não seja a maneira mais conveniente.

find *.tgz  -type f \
            \! -name Broad_hapmap3_r2_Affy6_cels_excluded.tgz \
            -exec tar xzf {} \;
    
por 16.02.2011 / 20:47
2

Para coisas pontuais como essa, eu apenas forcei:

for f in *.tgz; do 
   [[ "$f" != "Broad_hapmap3_r2_Affy6_cels_excluded.tgz" ]] && tar zxvf "$f"
done
    
por 16.02.2011 / 18:40