Bagaimana saya bisa memaksa unzip / zip untuk tidak membuat subdirektori ketika saya mengekstraknya?

19

Bergantung pada bagaimana file zip dibuat, kadang-kadang ia akan mengekstrak semua file secara langsung, dan kadang-kadang akan mengekstrak file ke dalam subdirektori.

Jika yang terakhir ini benar, bagaimana saya bisa memaksa unzipperintah untuk "mengabaikan" direktori tingkat pertama itu?

Contoh:

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

Yang saya dapatkan adalah /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/

Yang saya inginkan adalah file yang diekstraksi /tmp/omeka/, (satu tingkat dan tidak ada nomor versi yang termasuk dalam struktur direktori)

/tmp/omeka/(files)

Saya tahu saya bisa menggunakan -jopsi untuk "jalur sampah" tetapi saya ingin mempertahankan struktur subdirektori, hanya saja bukan struktur direktori tingkat atas. Bagaimana saya bisa melakukan ini?

cwd
sumber
ps: Saya sadar bahwa saya dapat mengekstraksi dan kemudian mvfile-file, tetapi saya ingin melihat apakah ada cara untuk melakukan ini langsung dari perintah unzip
cwd
Saya tidak menyadarinya. Tetapi jika nama file selalu cocok (terlepas dari ekstensi) nama direktori, itu cukup mudah untuk skrip mengubah nama dir yang diekstraksi.
Mat
3
Saya melihat apa yang Anda coba lakukan, tetapi saya tidak akan merekomendasikannya. Melucuti nomor versi dari sumber proyek Anda adalah ide yang buruk; Anda harus mengekstrak secara normal dan menggunakan ln -s jika Anda ingin nama yang lebih pendek tanpa informasi versi. Dengan begitu Anda selalu tahu versi apa yang sedang Anda jalankan dan dapat dengan mudah memperbarui ke versi baru dengan menukar tautan.
Burton Samograd
@ BurtonSamograd - itu akan ideal, tapi saya masih penasaran apakah ada cara yang efektif untuk melakukan ini karena beberapa perangkat lunak, ambil Wordpress sebagai contoh, menempatkan setiap versi di dalam /wordpress/direktori (tidak ada nomor versi) di dalam file zip. Memang baik untuk itu unzipdan kemudian, mvtetapi tidak memiliki kontrol ini dan harus melakukannya dalam dua langkah selalu membuat saya sedikit gugup. Untungnya Wordpress juga masuk dalam .tar.gzcitarasa :)
cwd
Cobacd /tmp/omeka && ln -s -T . omeka-1.5.1
James Youngman

Jawaban:

4

Gunakan sistem file FUSE yang memungkinkan Anda untuk menelusuri arsip seperti direktori, seperti AVFS . Gunakan cpuntuk mengekstrak file ke direktori pilihan Anda.

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

Karena kami mengasumsikan bahwa ada satu direktori tingkat teratas dalam arsip, Anda dapat mempersingkat ini menjadi

cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/* omeka
Gilles 'SANGAT berhenti menjadi jahat'
sumber
@Giles, Anda adalah ahli yang datang dan menjawab semua pertanyaan yang tidak bisa dijawab orang lain, jadi saya rasa ini adalah satu-satunya cara untuk melakukan ini. Saya berharap unzipmemiliki beberapa keajaiban untuk melakukan ini, seperti menentukan file yang akan diekstraksi seperti */*, yang dapat saya gunakan tanpa menginstal utilitas lain, tapi saya rasa tidak. Terima kasih. +1
cwd
6

Jika file zip Anda tidak mengandung struktur direktori atau Anda tidak perlu menyimpannya, Anda dapat menggunakan ini:

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

Skrip ini tidak kuat, tetapi berfungsi dalam kasus sederhana:

...
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

Itu hanya memeriksa untuk melihat apakah ada satu subdirektori, dan jika demikian, memindahkan semuanya dari sana lalu menghapusnya.

Steve Bennett
sumber
2

Saya baru saja mendaftar hari ini, jadi saya tidak bisa menjawab dengan jawaban @SteveBennet dan tidak dapat menambahkan komentar di sana.

Berdasarkan jawabannya saya membuat fungsi rekursif seperti ini:

...

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"

Seperti yang dikatakan @SteveBennet: skrip ini tidak kuat, tetapi berfungsi dalam kasus sederhana.

Semoga bermanfaat.

elysch
sumber
1

Perlu terlihat seperti patch --strip=nopsi

Akan diinginkan untuk memiliki opsi seperti patch --strip=number(atau -pnumber) yang memotong numberkomponen path di awal (ref. Membandingkan dan Menggabungkan File: patch Direktori ).

Solusi lain, penerapan

Gagal itu, ada solusi lain, jenis peretasan tetapi bekerja. Dalam kasus saya, saya ingin menimpa direktori yang penuh dengan file yang ada dengan isi zip, tanpa mengekstraksi zip penuh terlebih dahulu.

Ketika solusi ini bekerja dan solusi @ Gilles tersedia, yang terakhir juga akan berfungsi. Namun solusi ini tidak memerlukan ketersediaan sistem file FUSE.

Bagaimana cara melakukannya

Dengan asumsi Anda tahu direktori tambahan, dalam kasus omeka-1.5.1Anda, Anda dapat melakukan ini:

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

unzipakan mencoba unzip omeka-1.5.1yang sebenarnya merupakan symlink ke berisi dir. Akibatnya, file akan omekalangsung masuk.

Varian yang mungkin

Anda dapat membayangkan varian untuk mengarahkan ulang satu atau lebih bagian dari hierarki depeer.

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

Kesimpulan

Solusi ini agak spesifik, namun memiliki kasus penggunaannya dan saya kebetulan menggunakannya.

Stéphane Gourichon
sumber
Solusi hebat jika Anda tahu jalannya!
grepsedawk
Path dapat diselidiki dengan mendaftarkan konten zip terlebih dahulu, misalnya dengan unzip -l. Ini bahkan bisa diotomatisasi menggunakan skrip yang menggambarkan bagian dari jalur yang umum.
Stéphane Gourichon
Oh, benar-benar, itu hanya satu ton lebih mudah jika Anda tahu jalannya. Saya bermain dengan unzip -l untuk sedikit tetapi itu sedikit lebih grep / sed / awk daripada yang saya maksud jadi saya mundur.
grepsedawk
zipinfo -1mungkin awal yang baik. Apa kasus penggunaan Anda?
Stéphane Gourichon
github.com/grepsedawk/wow-config/blob/... dalam hal ini, saya tahu direktori :)
grepsedawk
1

Kemungkinan besar Anda ingin menjalankan unzipdengan -jpilihan, seperti pada:

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

Tetapi Anda mungkin akan terkejut dengan perilakunya:

jalur j-sampah. Struktur direktori arsip tidak diciptakan kembali; semua file disimpan dalam direktori ekstraksi (secara default, yang sekarang).

Jika Anda mengekstrak files.zipdi direktori keluaran ./outputdan Anda mendapatkan hasilnya:

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

maka -jopsi akan memberi Anda ini (semua jalur bergaris-garis):

./output/f1
./output/f2
Vincenzo Pii
sumber