Jak powiedział Mathias, unzip
nie ma takiej opcji, ale skrypt bash z jedną linią może to zrobić.
Problem polega na tym: najlepsze podejście zależy od układu archiwum. Rozwiązanie, które zakłada, że jeden katalog najwyższego poziomu zawiedzie, jeśli zawartość znajdzie się bezpośrednio w katalogu głównym archiwum (pomyśl o /a/foo
/b/foo
/foo
chaosie usuwania /a
i /b
).
To samo dzieje się z tar --strip-component
. Nie ma jednego uniwersalnego rozwiązania.
Tak więc, aby usunąć katalog główny, zakładając, że jest jeden (i tylko jeden):
unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"
Upewnij się tylko, że pliki / katalogi drugiego poziomu nie mają tej samej nazwy rodzica najwyższego poziomu (na przykład /foo/foo
). Ale /foo/bar/foo
i /foo/bar/bar
są w porządku. Jeśli tak, lub po prostu chcesz być bezpieczny, możesz użyć temp temp do ekstrakcji:
temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"
Jeśli używasz Bash, możesz sprawdzić, czy najwyższy poziom to pojedynczy katalog, czy nie używasz:
f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"
Mówiąc o Bash, należy włączyć, dotglob
aby dołączyć ukryte pliki, a wszystko można zawinąć w jedną, przydatną funkcję:
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"
)
Teraz włóż to do swojego ~/.bashrc
lub ~/.profile
już nigdy nie będziesz się o to martwić. Po prostu użyj jako:
unzip-strip sourcefile.zip mysubfolder
(zauważ, że utworzy się automatycznie mysubfolder
, jeśli nie istnieje)