Zip semua file dalam direktori?

483

Apakah ada cara untuk zip semua file dalam direktori yang diberikan dengan zipperintah? Saya pernah mendengar tentang penggunaan *.*, tetapi saya ingin itu berfungsi untuk file tanpa ekstensi juga.

tkbx
sumber
2
Sudahkah Anda mencoba menavigasi satu tingkat ke atas dari direktori yang Anda inginkan dan melakukan zip myarch.zip mydir/*?
Joseph R.
13
atau lebih baikzip -r myarch.zip mydir/*
Adam
25
atau lebih baikzip -r myarch.zip mydir
ctrl-alt-delor
*.*berarti file apa pun dengan titik. Dalam cp / m dan dos semua file memiliki titik, dan itu membuat Anda mengetiknya (tidak bisa melakukan *). Karena itu orang-orang datang untuk melihat *.*semua file. Akhirnya Microsoft menambahkan nama file panjang yang bisa memiliki nol, atau lebih banyak titik. Untuk menemukan file yang memiliki titik pada windows Anda harus mengetik *.*.*.
ctrl-alt-delor

Jawaban:

705

Anda bisa menggunakan *; tidak perlu untuk *.*. Ekstensi file tidak spesial di Unix. *cocok dengan nol atau lebih karakter — termasuk titik. Jadi cocok foo.png, karena itu nol atau lebih karakter (tujuh, tepatnya).

Perhatikan bahwa *secara default tidak cocok dengan file yang dimulai dengan titik (tidak juga *.*). Ini yang sering Anda inginkan. Jika tidak, dalam bash, jika Anda shopt -s dotglobmau (tapi masih akan mengecualikan .dan ..). Kerang lain memiliki cara yang berbeda (atau tidak sama sekali) untuk memasukkan dotfile.

Atau, zipjuga memiliki -ropsi (rekursif) untuk melakukan seluruh pohon direktori sekaligus (dan tidak perlu khawatir tentang masalah dotfile):

zip -r myfiles.zip mydir

di mana mydirdirektori berisi file-file Anda. Perhatikan bahwa zip yang dihasilkan akan berisi struktur direktori serta file. Seperti yang ditunjukkan peterph dalam komentarnya, ini biasanya dilihat sebagai hal yang baik: mengekstrak zip akan menyimpan semua file yang diekstrak dengan rapi dalam satu subdirektori.

Anda juga bisa memberi tahu zip untuk tidak menyimpan path dengan opsi -j/ --junk-paths.

The zipperintah dilengkapi dengan dokumentasi bercerita tentang semua nya (banyak) pilihan; ketik man zipuntuk melihat dokumentasi itu. Ini tidak unik untuk di-zip; Anda bisa mendapatkan dokumentasi untuk sebagian besar perintah dengan cara ini.

derobert
sumber
9
Anda mungkin ingin menambahkan, bahwa itu dianggap praktik yang baik untuk memuat semua yang ada di arsip di direktori tingkat atas - sehingga orang tidak mencemari direktori saat ini tentang ekstraksi.
peterph
@peterph selesai. Meskipun ini kurang konvensi dalam file zip daripada di misalnya, tarfiles, saya khawatir.
derobert
Sayangnya ya. Mungkin karena warisan windows dari drag'n'drop ke warisan desktop dan linux yang bekerja dengan kode sumber.
peterph
2
Perlu diingat bahwa *shell-globbing tidak termasuk dotfiles (mis. Nama file dimulai dengan .). Ini adalah keuntungan lain untuk zip seluruh direktori dengan nama.
mrb
Tetapi menggunakan -r termasuk direktori itu sendiri, yang memecah apa yang saya lakukan. Bukankah * termasuk .dan ..?
tkbx
11

Dalam kasus saya, saya ingin meng-zip setiap file ke dalam arsipnya sendiri, jadi saya melakukan yang berikut zsh:

$ for file in *; do zip ${file%.*}.zip $file; done
Radon Rosborough
sumber
1
Tidak ada mkvdisini? Juga tidak ada yang khusus di sini zsh. Anda ingin mengutip dengan benar variabel apa pun yang berisi nama file, jadi zip "${file%.*}.zip" "$file"dengan tanda kutip ganda di sekitar kedua variabel.
tripleee
1
@ tripleee Pertama, terima kasih telah menunjukkan referensi saya yang salah mkv. Kedua, mengutip argumen tidak perlu dalam zsh, tidak seperti di bash. Itu sebabnya saya menentukan bahwa ini adalah perintah untuk zsh.
Radon Rosborough
Mengganti semi-colon terakhir dengan ampersand mungkin mempercepatnya secara signifikan (Jika jumlah file dalam direktori masuk akal ...). Jika tidak find . -type f -maxdepth 1 -print0|xargs -r0 -n1 -P64 -I{} bash -c 'f="{}"; zip "${f%.*}.zip" "$f"'(dengan -Ppenyesuaian tergantung pada utas CPU Anda ...) (Banyak dependensi GNU ...)
Gert van den Berg
5

Cara lain adalah dengan menggunakan find dan xargs: (ini mungkin termasuk direktori "." Di zip, tetapi masih harus diekstrak dengan benar. Dengan pengujian saya, zip melepas titik sebelum kompresi) find . -type f -exec zip zipfile.zip {} +

( +Dapat diganti dengan \;jika versi findAnda tidak mendukung +akhir untuk eksekutif. Akan lebih lambat ...)

Ini secara default akan mencakup semua sub-direktori. Pada GNU temukan -maxdepthdapat mencegah itu.

Gert van den Berg
sumber
(tidak seperti solusi yang digunakan *, ini akan mencakup dotfiles dan tidak akan jatuh jika ada terlalu banyak file dalam direktori)
Gert van den Berg
1

Metode lain (lambat) untuk melakukan ini (yang menambahkan satu file ke zip sekaligus):

for f in * .[^.]*; do
    [ -r "$f" ] || continue # Skip directories or non-existant files (Probably ".[^.]*" if directory has no dotfiles). Using -e will allow directories to be used as well
    zip zipfile.zip "$f" # If directories are included, you probably want to add -r
done

Ini memiliki masalah dotfile *(solusi ditambahkan) dan akan mulai zip sekali untuk setiap file, menambahkannya ke arsip. Dalam bash, itu akan berurusan dengan sejumlah besar file.

Ini akan lebih lambat daripada kebanyakan metode lain, tetapi relatif sederhana.

Gert van den Berg
sumber
1
Saya akan mengatakan ini tidak sesederhana jawaban yang diterima, dan lebih lambat, yang memicu pertanyaan: "Mengapa ada orang yang melakukan ini?". Jika Anda dapat menjawab pertanyaan itu, saya sarankan Anda meletakkan konteks itu dalam jawaban Anda, jika tidak, saya pikir itu adalah jawaban yang buruk untuk pertanyaan lama yang sudah memiliki jawaban yang baik.
Centimane
@Centimane: Saya perhatikan batasannya. Saya merasa ini memiliki nilai pendidikan. (Jika tidak melewatkan direktori, ini cukup sederhana). Jika Anda menginginkan jawaban yang jauh lebih cepat menggunakan alat eksternal (standar), jawaban saya yang lain mencakup itu. (dengan penanganan dotfiles dihapus (yang mempengaruhi kebenaran tanpa ketidakhadiran mereka disebutkan dalam pertanyaan), saya merasa itu cukup elegan):for f in *; do zip zip.zip "$f"; done
Gert van den Berg
1
Perhatikan bahwa jawaban yang diterima tidak menggunakan perintah eksternal dan akan lebih cepat. Dalam skenario apa jawaban ini berguna?
Centimane
@Centimane Dengan tar ketika ada lebih banyak file daripada yang bisa dilewati bash sebagai parameter. (temukan + xarg lebih baik, karena loop lebih mudah ...). Ini adalah jawaban (unik) untuk pertanyaan itu. Ini tentu bukan jawaban yang optimal. (Jawaban yang tidak optimal masih dapat berguna untuk masalah yang serupa, jika seseorang memiliki situasi yang sedikit berbeda - misalnya menginginkan file tar direktori di dalamnya)
Gert van den Berg