Equivalente ao tar '--strip-components = 1' no unzip?

41

Eu tenho um script que extrai um arquivo tar.gz para um subdiretório especificado mysubfolder :

mkdir mysubfolder; tar --extract --file=sourcefile.tar.gz --strip-components=1 --directory=mysubfolder;

Existe alguma maneira equivalente de fazer isso com um arquivo zip?

    
por frigg 12.12.2012 / 12:58

2 respostas

22

Como Mathias disse, unzip não tem essa opção, mas um script bash de uma linha pode fazer o trabalho.

O problema é: a melhor abordagem depende do layout do seu arquivo. Uma solução que assume um único diretório de nível superior falhará miseravelmente se o conteúdo estiver diretamente na raiz do arquivo (pense em /a/foo /b/foo /foo e no caos de remoção de /a e %código%).

E a mesma falha acontece com /b . Não existe uma solução única para todos.

Então, para remover o diretório raiz, assumindo que seja um (e somente um):

unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"

Apenas certifique-se de que os arquivos / dirs de segundo nível não tenham o mesmo nome do pai de nível superior (por exemplo, tar --strip-component ). Mas /foo/foo e /foo/bar/foo estão ok. Se o fizerem, ou se você apenas quiser estar seguro, poderá usar um diretório temporário para extração:

temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"

Se você estiver usando o Bash, poderá testar se o nível superior é um único diretório ou não está usando:

f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"

Falando em Bash, você deve ativar /foo/bar/bar para incluir arquivos ocultos e pode incluir tudo em uma única função prática:

unzip-strip() (
    local zip=$1
    local dest=${2:-.}
    local temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
    shopt -s dotglob && local f=("$temp"/*) &&
    if (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] ; then
        mv "$temp"/*/* "$dest"
    else
        mv "$temp"/* "$dest"
    fi && rmdir "$temp"/* "$temp"
)

Agora coloque isso no seu dotglob ou ~/.bashrc e você nunca terá que se preocupar com isso novamente. Simplesmente use como:

unzip-strip sourcefile.zip mysubfolder

(observe que será criado automaticamente ~/.profile para você, se não existir)

    
por 28.03.2013 / 10:36
2

Não encontrei essa opção em as páginas de manual de unzip , então eu tenho medo que isso seja impossível. : (

No entanto, (dependendo da situação) você pode contornar isso. Por exemplo, se você tem certeza de que o único diretório de nível superior no arquivo zip é denominado foo- seguido por um número de versão, você poderia fazer algo assim:

cd /tmp
unzip /path/to/file.zip
cd foo-*
cp -r . /path/to/destination/folder
    
por 13.12.2012 / 12:50

Tags