Yanıtlar:
Mathias'in dediği unzip
gibi, böyle bir seçeneğe sahip değil, ancak bir liner bash betiği işi yapabilir.
Sorun şudur: en iyi yaklaşım arşiv düzeninize bağlıdır. İçeriği doğrudan arşiv kökünde ise (üstünü sıyırıp sıyrılmanın ve kaosun kaosunu düşünün) tek bir üst düzey direk varsayan bir çözüm sefil bir şekilde başarısız olacaktır ./a/foo
/b/foo
/foo
/a
/b
Ve aynı başarısızlık da olur tar --strip-component
. Tek bedene uyan tek bir çözüm yoktur.
Böylece, bir tane (ve sadece bir tane) olduğunu varsayarak, kök dizinini soymak için :
unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"
İkinci seviye dosyaların / dizinlerin üst seviye üst öğenin adıyla aynı olmadığından emin olun (örneğin, /foo/foo
). Ama /foo/bar/foo
ve /foo/bar/bar
tamam. Eğer yaparlarsa veya sadece güvende olmak istiyorsan, çıkarma için geçici bir dir kullanabilirsin:
temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"
Bash kullanıyorsanız, üst seviyenin tek bir dir olup olmadığını test edebilirsiniz:
f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"
Bash'den bahsederken, dotglob
gizli dosyaları dahil etmek için açmalısınız ve her şeyi tek bir kullanışlı fonksiyona sarabilirsiniz:
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"
)
Şimdi bunu kendinize koyun ~/.bashrc
ya da bir ~/.profile
daha asla endişelenmenize gerek kalmayacak. Basitçe kullanın:
unzip-strip sourcefile.zip mysubfolder
( mysubfolder
yoksa sizin için otomatik olarak oluşturacağına dikkat edin )
Manuel sayfalardaunzip
böyle bir seçenek bulamadım , korkarım bu imkansız. :(
Ancak, (duruma bağlı olarak) bunun etrafında çalışabilirsiniz. Örneğin, zip dosyasındaki tek üst düzey dizinin foo-
ardından bir sürüm numarasıyla adlandırıldığından eminseniz, şöyle bir şey yapabilirsiniz:
cd /tmp
unzip /path/to/file.zip
cd foo-*
cp -r . /path/to/destination/folder
rm -rf foo-*
potansiyel olarak tehlikeli olduğundan bilerek eklemedim . Ya zaten adında bir klasör varsa foo-bar
? Çıkartma işleminin /tmp
, her seferinde ve sonrasında otomatik olarak boşaltılan klasör içerisinde yapıldığını unutmayın .
&&
: verilen bir adım sadece önceki adım başarılı olursa gerçekleşir, yani son adım (ancak rm
) yalnızca tüm adımlar hatasız bir şekilde tamamlanırsa çalışır .
/tmp/some-hardcoded-folder-name
geçici klasör olarak kullanılmamalı, bunun yerine bunun kullanılmalı mktemp
: böyle bir klasör bulunmayacağının garantisi. Aşağıdaki cevabımı kontrol et.
-j
Yolları önemsiz yapmak için kullanabilirsiniz (dizin oluşturmayın). Bu, yalnızca ortak tek seviyeli arşivler için önerilir. Çok seviyeli dizin yapılarına sahip arşivler düzleştirilecektir - bu, dosyaların çıkartılması için isim çakışmalarına bile yol açabilir.
Sıkıştırmayı aç sayfasındaki man sayfasından:
-j junk paths. The archive's directory structure is not recreated; all files are deposited in the extraction directory (by default, the current one).