Junk uma parte do diretório com descompactar?

3

Um arquivo zip f.zip contém um monte de arquivos, todos com diretórios.

 A/B
 A/B/C
 A/B/C/D

 ..
 A/B/C/D/and/some/more/dirs
 A/B2

Agora estou interessado apenas na árvore abaixo de C / D. Eu posso fazer unzip f.zip */D/* -d . , que descompacta tudo em D - assumindo que D é uma seqüência única - para o diretório atual, incluindo A / B / C, no entanto, quero que D seja a raiz da minha ação de descompactação. É claro que posso simplesmente mover D para meu diretório de trabalho atual, mas considero essa trapaça.

Man pages nem o google revelaram uma solução, mas talvez eu esteja negligenciando e talvez haja uma solução melhor do que se mudar ...

Oh minha plataforma é mac os x 10.8.prettyup2date

    
por dr jerry 07.08.2013 / 10:54

2 respostas

2

Por meio da página de manual do unzip:

   -j     junk paths.  The archive's directory structure is not recreated;
     all files are deposited in the extraction directory (by default,
     the current one).

Então:

unzip -d D -j f.zip */D/*

Extraia tudo para uma pasta chamada D, mas sem estrutura de diretório (observe que isso extrairá arquivos nos subdiretórios de D para a pasta D de nível superior).

O

EDIT OP queria manter a estrutura do arquivo sob a pasta D.

unzip -l f.zip | grep 'A/B/C/D' | \
perl -ple 's/\s+\d+\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+(.*)$/$1/' | \
while read file
do 
    unzip -j -d "$(echo $file | sed 's:A/B/C/\(.*\)/.*::g')" f.zip "$file"
done

Cada passo em partes:

unzip -l f.zip

obtenha uma lista de arquivos em f.zip

grep 'A/B/C/D'

mostre as linhas que mostram arquivos no diretório de destino

perl -ple 's/\s+\d+\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+(.*)$/$1/'

use o perl para obter o nome do arquivo naquela linha correspondente (meu sed-fu não é tão bom quanto o de Stephane, então usarei o perl!), NOTE que isso lida com espaços em nomes de arquivos : )

while read file
do

percorra os arquivos produzidos a partir dos comandos acima e atribua-o a $file

unzip -j -d "$(echo $file | sed 's:A/B/C/\(.*\)/.*::g')" f.zip "$file" 

descompacte o destino $file , refazendo seu caminho, no diretório de destino obtido de

echo $file | sed 's:A/B/C/\(.*\)/.*::g'

que remove o caminho A / B / C / inicial do nome do arquivo, observe que ele é empacotado em $ () (a Command substitution , consulte bash para obter mais detalhes) e que a substituição de comandos está entre aspas duplas para preservar espaços (e realmente avaliar o $() ).

done

conclui o loop.

Isso, na verdade, executa uma operação de descompactação para cada arquivo correspondente em A / B / C:

unzip -j -d "D" f.zip "A/B/C/D/"
unzip -j -d "D" f.zip "A/B/C/D/b"
unzip -j -d "D" f.zip "A/B/C/D/e"
unzip -j -d "D/stupid space" f.zip "A/B/C/D/stupid space/"
unzip -j -d "D/stupid space" f.zip "A/B/C/D/stupid space/b"
unzip -j -d "D/stupid space" f.zip "A/B/C/D/stupid space/e"
unzip -j -d "D/stupid space" f.zip "A/B/C/D/stupid space/d"
unzip -j -d "D/stupid space" f.zip "A/B/C/D/stupid space/c"
unzip -j -d "D/stupid space" f.zip "A/B/C/D/stupid space/a"
unzip -j -d "D" f.zip "A/B/C/D/d"
unzip -j -d "D" f.zip "A/B/C/D/f"

Se você executar esse comando para extrair uma estrutura de arquivos já existente, precisará adicionar mais -o a override arquivos existentes (ou a primeira operação de descompactação que bloqueará um arquivo será solicitada com replace D/b? [y]es, [n]o, [A]ll, [N]one, [r]ename: extracting: D/b e então bombardeie para fora). Se você precisar desse aviso, terá que usar outro método de looping que não use read e também lida com espaços ( for $( ... ) falhará no teste). Vou deixar isso como um exercício para você se exercitar se precisar fazer isso!

    
por 07.08.2013 / 11:32
1

Monte o zip como um diretório. Você pode fazer isso através do FUSE , uma estrutura genérica para drivers de sistema de arquivos implementados por programas comuns em vez de drivers de kernel. Instale o OSXFUSE (suporte genérico ao FUSE no OSX), depois fuse-zip (um driver FUSE para arquivos zip). Depois de instalar o software necessário, monte o arquivo:

mkdir /tmp/myzip
fuse-zip f.zip /tmp/myzip

Agora você pode acessar os arquivos no zip como se fosse um diretório. Para extrair A/B/C/D , copie-o:

cp -Rp /tmp/myzip/A/B/C/D /some/where

Desmonte o zip quando terminar.

fusermount -u /tmp/myzip
rmdir /tmp/myzip

Se você quiser pular o software pré-instalado, acho que você precisa descompactar A/B/C/D e depois mover o diretório.

    
por 08.08.2013 / 02:01

Tags