Bagaimana cara men-zip banyak file di command line?

16

Maafkan pertanyaan paling mendasar ini, tetapi saya tidak dapat menemukan jawaban langsung atau contoh sederhana tentang pertukaran tumpukan.

Katakanlah saya memiliki folder file yang ingin saya kompres menjadi satu file zip yang dapat saya bagikan dengan teman-teman Windows saya yang mengerikan (jika tidak, saya hanya akan menggunakan tardan selesai dengan itu). Ini terlihat seperti ini:

.
├── file1.txt
├── file2.txt
├── file3.txt
├── file.jpg
└── test.jpg

Dengan asumsi saya telah zipmenginstal:

sudo apt-get install zip

Saya melihat dari man zipitu memungkinkan saya untuk menggunakan daftar file:

- @ daftar file. Jika daftar file ditentukan sebagai - @ [Bukan pada MacOS], zip akan mengambil daftar file input dari input standar alih-alih dari baris perintah. Sebagai contoh,

          zip -@ foo

Jadi saya buat zip.lstyang terlihat seperti ini:

cat zip.lst

file1.txt
file2.txt
file3.txt
file.jpg
test.jpg

Dan sekarang saya mencoba:

zip -@ zip.lst

Tapi itu tidak melakukan apa pun kecuali membuat garis kosong di konsol. Dan saya bisa terus mendorongEnter dan terus membuat lebih banyak baris kosong tanpa tampaknya menjalankan perintah. Setelah beberapa pencarian, saya menyadari bahwa saya perlu menghentikan input dengan menekan Ctrl+D

Tapi sekarang saya mendapatkan kesalahan ini:

    zip warning: missing end signature--probably not a zip file (did you
    zip warning: remember to use binary mode when you transferred it?)
    zip warning: (if you are trying to read a damaged archive try -F)

zip error: Zip file structure invalid (zip.lst)

Apa!? Bagaimana daftar sederhana saya bukan "struktur file yang valid"? Kembali ke manual untuk informasi lebih lanjut, dan saya melihat lebih dekat:

Jika daftar file ditentukan sebagai - @ ...

Jadi saya mencobanya tanpa -@, dan setidaknya memprosesnya segera tanpa harus menekan Ctrl+ Dtetapi saya pergi dengan kesalahan yang sama .

Untungnya, saya menemukan komentar pada jawaban untuk pertanyaan yang hampir tidak berhubungan yang membuat saya menyadari bahwa saya perlu secara eksplisit memberi nama file zip. Kesalahan ini karena secara default mencoba membuat file zip bernama zip.lst. Tetapi karena itulah nama daftar saya, orang mungkin berpikir bahwa itu hanya akan menimpanya, tetapi tidak, itu sebenarnya mencoba memperbaruinya. Dan karena daftar itu jelas bukan file zip, kami mendapatkan kesalahan struktur file yang tidak valid, dan sekarang jelas mengapa dikatakan "mungkin bukan file zip." Jadi saya mencoba:

zip files.zip zip.lst

adding: zip.lst (deflated 35%)

Eureka! Saya dapat melihat file zip dibuat dan folder saya sekarang berisi ini:

.
├── file1.txt
├── file2.txt
├── file3.txt
├── file.jpg
├── files.zip
├── test.jpg
└── zip.lst

Tapi tunggu dulu sebelum kita merayakannya, mari kita konfirmasi dulu isi file zip:

unzip -l files.zip

Archive:  files.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       48  2016-05-24 15:30   zip.lst
---------                     -------
       48                     1 file

Tidak!Yah, sebenarnya itu masuk akal dari penggunaan standar karena hanya zip file satu daftar yang saya berikan. Akhirnya saya mencoba lagi dengan -@tetapi mendapat hasil yang sama.

Apa yang saya lakukan salah?

BTW, saya tahu saya bisa menggunakan GUI dan melakukannya dengan mouse saya, tetapi saya perlu menulis skrip ini, dan secara umum saya lebih cepat menggunakan CLI ketika saya tahu apa yang saya lakukan.

Jeff Puckett
sumber

Jawaban:

23

Gunakan <pengalihan file

zip files.zip -@ < zip.lst

Atau Anda bisa melewati daftar dan hanya glob

zip files.zip *.txt *.jpg

terima kasih steeldriver

Jawaban Historis

Saya senang tidak apa-apa untuk menjawab pertanyaan saya sendiri karena saya ingin mencatat kekacauan saya dengan harapan bahwa orang lain yang mengikuti jejak saya dapat terhindar dengan mencari beberapa kata kunci.

Akhirnya, saya menemukan jawaban yang benar , tetapi itu diposting ke pertanyaan yang salah .

Beberapa poin kejelasan:

  • Manual ini tidak merujuk ke daftar literal seperti dalam file, melainkan secara harfiah untuk daftar file di konsol.
  • Dapat dimengerti bahwa seseorang mungkin disesatkan untuk berpikir seperti itu foo merujuk pada daftar file, tetapi sebenarnya dimaksudkan untuk mewakili nama file zip output.
  • Daftar file dihilangkan dalam contoh karena menggunakan -@saklar, yang menunjukkan itu "mengambil daftar file input dari input standar, bukan dari baris perintah "

Memahami ini, kita sekarang dipersenjatai dengan berbagai cara untuk mencapai tujuan.

Pertama menggunakan daftar file yang kita buat, kita dapat membaca daftar dengan catdan mengarahkan output dengan pipa sebagai input standar ke zip:

cat zip.lst | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

Melihat bahwa adding: ...untuk setiap file tentu merupakan pertanda yang baik, tetapi kami sudah memiliki harapan kami sebelumnya, jadi mari kita konfirmasikan:

unzip -l files.zip

Archive:  files.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2016-05-24 14:54   file1.txt
        0  2016-05-24 14:54   file2.txt
        0  2016-05-24 14:54   file3.txt
        0  2016-05-24 15:00   file.jpg
        0  2016-05-24 14:59   test.jpg
---------                     -------
        0                     5 files

MANIS! Tapi siapa yang tetap ingin membuat daftar sekali pakai? Itu cara yang sulit untuk menyelesaikan skenario khusus ini. Akan lebih baik untuk mendapatkan daftar dari lsdan pipa itu ke zip:

ls | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

Menakjubkan! Sekarang mari kita buat filter dengan kekuatan luar biasa grepuntuk hanya men-zip jpg misalnya:

ls | grep .jpg | zip -@ images.zip

  adding: file.jpg (stored 0%)
  adding: test.jpg (stored 0%)

Atau hanya file yang diawali dengan "file"

ls | grep file. | zip -@ files.zip

  adding: file1.txt (stored 0%)
  adding: file2.txt (stored 0%)
  adding: file3.txt (stored 0%)
  adding: file.jpg (stored 0%)
Jeff Puckett
sumber
5
Alih-alih menggunakan lsdan grepdan zip -@, Anda dapat menggunakan shell shell untuk memilih file secara langsung pada baris perintah zip misalnya zip files.zip file*atau zip images.zip *.jpg. Juga, saat menggunakan daftar nama file dari suatu file, Anda dapat menggunakan pengalihan alih-alih memanggil proses kucing yang terpisah,zip files.zip -@ < zip.lst
steeldriver
Bagaimana Anda bisa membuat ini bekerja dengan direktori bersarang di samping file?
BallpointBen
@BallpointBen Saya akan menggunakan findbukannyals
Jeff Puckett
6

perintah paling sederhana dengan tingkat kompresi maksimal

zip -9 -r filename.zip /path/to/dir singlefile.jpg 
Ansyori
sumber