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 pressupõe que um único diretório de nível superior falhe miseravelmente se o conteúdo estiver diretamente na raiz do arquivo morto (pense /a/foo
/b/foo
/foo
no caos de remover /a
e remover /b
).
E a mesma falha acontece com tar --strip-component
. Não existe uma solução única para todos.
Assim, para retirar o directório raiz, assumindo que não é um (e única um):
unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"
Apenas verifique se os arquivos / diretórios de segundo nível não têm o mesmo nome do pai de nível superior (por exemplo /foo/foo
). Mas /foo/bar/foo
e /foo/bar/bar
está bem. Se sim, ou você apenas quer estar seguro, pode 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:
f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"
Por falar em Bash, você deve ativar dotglob
para incluir arquivos ocultos e pode agrupar tudo em uma única função útil:
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 ~/.bashrc
ou ~/.profile
e você nunca mais precisará se preocupar com isso. Basta usar como:
unzip-strip sourcefile.zip mysubfolder
(observe que ele será criado automaticamente mysubfolder
se não existir)