Как мне заархивировать несколько файлов в командной строке?

16

Простите за этот самый основной вопрос, но я не смог найти прямой ответ или простой пример по обмену стека.

Допустим, у меня есть папка с файлами, которую я хотел бы сжать в один zip-файл, которым я мог бы поделиться со своими ужасными друзьями из Windows (иначе я бы просто использовал tarи покончил с этим). Это выглядит так:

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

Предполагая, что я zipустановил:

sudo apt-get install zip

Я вижу, man zipчто это позволяет мне использовать список файлов:

- @ списки файлов. Если список файлов указан как - @ [Не в MacOS], zip берет список входных файлов из стандартного ввода, а не из командной строки. Например,

          zip -@ foo

Итак, я создал zip.lstчто выглядит так:

cat zip.lst

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

И теперь я попробовал:

zip -@ zip.lst

Но он ничего не делал, кроме создания пустой строки на консоли. И я могу продолжать нажимать, Enterи он просто продолжает делать больше пустых строк, не выполняя, казалось бы, команду. После некоторых поисков я понял, что мне нужно прекратить ввод, нажав Ctrl+D

Но теперь я получаю эту ошибку:

    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)

Какая!? Как мой простой список не является "допустимой файловой структурой"? Обратитесь к руководству для получения дополнительной информации, и я более подробно рассмотрю:

Если список файлов указан как - @ ...

Поэтому я пробую это без -@, и это, по крайней мере, обрабатывает его сразу, не нажимая Ctrl+, Dно у меня остается та же ошибка .

К счастью, я нашел комментарий к ответу на почти не связанный вопрос, который привел меня к осознанию того, что мне нужно явно назвать zip-файл. Эта ошибка была вызвана тем, что по умолчанию она пыталась создать zip-файл с именем zip.lst. Но так как это название моего списка, можно подумать, что он просто перезапишет его, но нет, на самом деле он пытался обновить его. И поскольку список, очевидно, не является zip-файлом, мы получаем ошибку неверной структуры файла, и теперь понятно, почему он сказал «вероятно, не zip-файл». И тогда я попробовал:

zip files.zip zip.lst

adding: zip.lst (deflated 35%)

Эврика! Я вижу, что zip-файл был создан, и моя папка теперь содержит это:

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

Но подождите, прежде чем мы отпразднуем, давайте сначала подтвердим содержимое zip-файла:

unzip -l files.zip

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

Нет! Ну, на самом деле это имеет смысл из стандартного использования, потому что он просто сжал один файл списка, который я дал. Наконец я попробовал еще раз, -@но получил тот же результат.

Что я делаю неправильно?

Кстати, я знаю, что могу использовать графический интерфейс и делать это с помощью мыши, но мне нужно написать скрипт, и в целом я быстрее использую CLI, когда знаю, что делаю.

Джефф Пукетт
источник

Ответы:

23

Использовать <перенаправление файлов

zip files.zip -@ < zip.lst

Или вы можете пропустить список и просто шарить

zip files.zip *.txt *.jpg

спасибо SteelDriver

Исторический ответ

Я рад, что все в порядке, чтобы ответить на мой собственный вопрос, потому что я хотел вести хронику своей суматохи в надежде, что другие, следующие за мной в слезах, могут быть спасены, ища некоторые ключевые слова.

В конце концов я нашел правильный ответ , но он был отправлен на неправильный вопрос .

Пара моментов ясности:

  • Руководство не ссылается на буквальный список, как в файле, а скорее на список файлов на консоли.
  • Понятно, что кто-то может быть введен в заблуждение, думая, что он fooссылается на список файлов, но на самом деле он предназначен для представления имени выходного zip-файла.
  • Список файлов в примере опущен, поскольку он использует -@переключатель, который демонстрирует, что он «берет список входных файлов из стандартного ввода, а не из командной строки »

Понимая это, мы теперь вооружены различными способами для достижения цели.

Во-первых, используя список файлов, который мы создали, мы можем прочитать список catи перенаправить вывод с конвейером в качестве стандартного ввода в 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%)

Видеть, что adding: ...для каждого файла это, безусловно, хороший знак, но мы надеялись раньше, поэтому давайте просто подтвердим:

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

СЛАДКИЙ! Но кто все равно хочет создать одноразовый список? Это ужасный обходной путь решения этого конкретного сценария. Было бы лучше получить список lsи отправить его по 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%)

Потрясающе! Теперь давайте создадим фильтры с удивительной силой, например, grepпросто сжать файлы jpg:

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

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

Или просто файлы, начинающиеся с «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%)
Джефф Пукетт
источник
5
Вместо использования lsи grepи zip -@можно использовать глобусы оболочки для выбора файлов непосредственно в командной строке zip, например zip files.zip file*или zip images.zip *.jpg. Кроме того, при использовании списка имен файлов из файла вы можете использовать перенаправление вместо вызова отдельного процесса cat,zip files.zip -@ < zip.lst
steeldriver
Как вы можете сделать это работать с вложенными каталогами вместе с файлами?
BallpointBen
@BallpointBen Я бы использовал findвместоls
Джефф Пукетт
6

самая простая команда с максимальным уровнем сжатия

zip -9 -r filename.zip /path/to/dir singlefile.jpg 
Ansyori
источник