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)