Ayıkladığımda alt dizini oluşturmamak için unzip / zip komutunu nasıl zorlayabilirim?


19

Bir zip dosyasının nasıl oluşturulduğuna bağlı olarak, bazen tüm dosyaları doğrudan çıkarır, bazen de dosyaları bir alt dizine çıkarır.

İkincisi doğruysa, unzipkomutu ilk düzey dizini "yoksaymaya" nasıl zorlayabilirim ?

Misal:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
mkdir omeka
unzip omeka-1.5.1.zip -d omeka/
cd omeka/
ll

Ne alıyorum /tmp/omeka/omeka-1.5.1/:

total 12
drwxr-xr-x 3 root root 4096 2012-05-08 18:44 ./
drwxrwxrwt 6 root root 4096 2012-05-08 18:44 ../
drwxr-xr-x 5 root root 4096 2012-04-20 14:54 omeka-1.5.1/

Ne istediğim /tmp/omeka/, (bir seviye yukarı ve dizin yapısında hiçbir sürüm numarası dahil) ayıklanan dosyaları

/tmp/omeka/(files)

Ben -j"önemsiz yollar" seçeneği kullanabilirsiniz biliyorum ama ben sadece üst düzey dizin yapısı değil, alt dizin yapısı tutmak istiyorum. Bunu nasıl yapabilirim?


ps: mvDosyaları ayıklayabildiğimin ve sonra dosyaları açabileceğimin farkındayım , ancak bunu unzip komutundan hemen yapmanın bir yolu olup olmadığını görmek istedim
cwd

Birinin farkında değilim. Ancak dosya adı her zaman dizin uzantısıyla eşleşiyorsa (uzantı dışında), ayıklanan dizinin adını yeniden adlandırmak oldukça basittir.
Mat

3
Ne yapmaya çalıştığınızı görüyorum, ama tavsiye etmem. Sürüm numarasını proje kaynaklarınızdan çıkarmak kötü bir fikirdir; sürüm bilgisi olmadan daha kısa bir ad istiyorsanız, normal olarak ayıklamanız ve bir ln -s kullanmanız gerekir. Bu şekilde hangi sürümü kullandığınızı her zaman bilirsiniz ve bağlantıyı değiştirerek yeni bir sürüme kolayca güncelleyebilirsiniz.
Burton Samograd

@BurtonSamograd - bu ideal olurdu, ancak yine de bunu yapmanın etkili bir yolu olup olmadığını merak ediyorum çünkü bazı yazılımlar, Wordpress'i örnek olarak alıyor, her sürümü /wordpress/zip dosyasının içine bir dizinin içine (sürüm numarası yok) koyuyor . Gerçekten unzipve sonra gayet iyi mvama bunun hiçbir kontrolü yok ve iki adımda yapmak zorunda kaldım, her zaman sinirlerimde biraz oldu. Neyse ki Wordpress de bir .tar.gzlezzet
içeriyor

Deneyincd /tmp/omeka && ln -s -T . omeka-1.5.1
James Youngman

Yanıtlar:


4

AVFS gibi dizinler gibi arşivlere göz atmanıza izin veren bir FUSE dosya sistemi kullanın . Dosyaları istediğiniz dizine çıkarmak için kullanın .cp

mountavfs
cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/omeka-1.5.1 omeka

Arşivde tek bir üst düzey dizin bulunduğunu varsaydığımız için bunu kısaltabilirsiniz.

cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/* omeka

@Giles, kimsenin cevaplayamayacağı tüm soruları cevaplayan ve cevap veren uzmansınız, bu yüzden bunu yapmanın tek yolu bu. Ben umuyordum unzipböyle gibi ayıklanmasını dosyalar belirterek olarak, bunu yapmak için biraz sihir vardı */*ben başka programı yüklemeden kullanabileceği, ama sanırım değil. Teşekkürler. +1
cwd

6

Zip dosyanız dizin yapısı içermiyorsa veya korumanız gerekmiyorsa, bunu kullanabilirsiniz:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
unzip -j omeka-1.5.1.zip -d omeka
cd omeka
ll

3

Bu komut dosyası sağlam değildir, ancak basit durumlarda çalışır:

...
dest=omeka
unzip omeka-1.5.1.zip -d $dest/

if [ `ls $dest | wc -l` == 1 ]; then
  subdir=`ls $dest`
  mv $dest/$subdir/* $dest/
  rmdir $dest/$subdir
fi

Sadece bir alt dizinin olup olmadığını kontrol eder ve eğer öyleyse, her şeyi onun dışına taşır ve sonra siler.


2

Bugün yeni kaydoldum, bu yüzden @SteveBennet yanıtını oylayamıyorum ve orada yorum ekleyemiyorum.

Cevabına dayanarak böyle bir özyinelemeli fonksiyon yarattım:

...

shopt -s dotglob # To include hidden files in the move command

function moveSub {
  local dest=$1
  if [ `ls $dest | wc -l` == 1 ]; then
    local subdir=`ls $dest`
    moveSub "$dest/$subdir"
    mv $dest/$subdir/* $dest/
    rmdir $dest/$subdir
  fi
}

moveSub "$dest"

@SteveBennet'in dediği gibi: bu senaryo sağlam değil, basit durumlarda çalışıyor.

Umarım faydalıdır.


1

patch --strip=nSeçenek gibi görünüyor

Başlangıçta yol bileşenlerini kesen patch --strip=number(veya -pnumber) gibi bir seçeneğe sahip olmak istenir number(ref. Dosyaları Karşılaştırma ve Birleştirme: yama Dizinleri ).

Diğer çözüm, uygulanabilirlik

Bunu başaramazsanız, başka bir çözüm var, bir tür hackish ama işe yarıyor. Benim durumumda, ilk olarak tam zip'i çıkarmadan, zip dosyası içeren mevcut dosyalarla dolu bir dizinin üzerine yazmak istedim.

Bu çözüm işe yaradığında ve @ Gilles'in çözümü mevcut olduğunda, bu çözüm de işe yarayacaktır. Ancak bu çözüm bir FUSE dosya sisteminin kullanılabilirliğini gerektirmez.

Nasıl yapılır

Ek dizini bildiğinizi varsayarsak omeka-1.5.1, bunu yapabilirsiniz:

mkdir omeka
ln -s . omeka/omeka-1.5.1 # create a symlink that redirects output
unzip omeka-1.5.1.zip -d omeka/
rm omeka/omeka-1.5.1 # remote symlink

unzipomeka-1.5.1dir içeren bir symlink olan unzip etmeye çalışacağız . Sonuç olarak, dosyalar omekadoğrudan gelecektir .

Olası varyantlar

Bir depeer hiyerarşisinin bir veya daha fazla bölümünü yönlendirmek için varyantlar hayal edebilirsiniz.

ln -s ../myfoo omeka/omeka-1.5.1/foo
ln -s ../../mybarxyzzy omeka/omeka-1.5.1/subdir/bar

Sonuç

Bu çözüm biraz spesifiktir, ancak kullanım durumları vardır ve bunu kullanıyorum.


Yolu biliyorsanız harika bir çözüm!
grepsedawk

Yol, önce zip içeriği listelenerek incelenebilir, örn unzip -l. İle . Bu, yaygın olan yolun bir kısmını belirleyen bir komut dosyası kullanılarak otomatikleştirilebilir.
Stéphane Gourichon

Tamamen, yolu biliyorsanız sadece bir ton daha kolay. Biraz unzip -l ile oynadım ama bu yüzden yedeklediğimden daha fazla grep / sed / awk oldu.
grepsedawk

zipinfo -1iyi bir başlangıç ​​olabilir. Kullanım durumunuz nedir?
Stéphane Gourichon

github.com/grepsedawk/wow-config/blob/… bu durumda, dizini biliyorum :)
grepsedawk

1

Büyük olasılıkla çalıştırmak istediğiniz unzipile -jolduğu gibi, seçenek:

unzip -j files.zip -d ./output/

Ancak davranışlarından şaşırabilirsiniz:

-j önemsiz yollar. Arşivin dizin yapısı yeniden oluşturulmaz; tüm dosyalar ayıklama dizininde depolanır (varsayılan olarak geçerli dosya).

Eğer ayıklarsanız files.zipçıktı dizinde ./outputve bunun sonucunda bu olsun:

./output/files/subfolder1/f1
./output/files/subfolder1/f2

Sonra -jseçeneği (bütün yollar çizgili) bu verecektir:

./output/f1
./output/f2
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.