Как вы указываете имена файлов в zip-архиве при его создании в командной строке из канала?

Я пытаюсь создать zip-файл из содержимого файла, которое передается, например.

mysql [params and query] | zip -q output.zip -

Это правильно пишет zip, но когда вы открываете zip, файл внутри него называется "-". Есть ли способ указать, какое имя файла передаваемых данных должно быть внутри zip?


person Community    schedule 07.01.2010    source источник
comment
Пожалуйста, не отмечайте вопросы как принадлежащие суперпользователю (или принадлежащие кому-либо еще) — просто проголосуйте за их перемещение.   -  person    schedule 07.01.2010
comment
@Нил Полностью с тобой согласен!   -  person Peter Lindqvist    schedule 07.01.2010


Ответы (6)


Из того, что я могу понять, вы не можете сделать и то, и другое с помощью команды zip, я имею в виду, что вы не можете одновременно указывать имена файлов и передавать содержимое. Вы можете либо передать содержимое, и результирующий файл будет -, либо вы можете передать имена файлов с помощью -@.

Это не означает, что это невозможно сделать с помощью других методов. Я обрисовываю один из них ниже. Это означает, что у вас должен быть установлен PHP и загружено расширение zip.

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

Это рабочий пример с использованием PHP

echo contents | php -r '$z = new ZipArchive();$z->open($argv[1],ZipArchive::CREATE);$z->addFromString($argv[2],file_get_contents("php://stdin"));$z->close();' test.zip testfile

Для запуска в Windows просто поменяйте местами одинарные и двойные кавычки. Или просто поместите скрипт в файл.

«test.zip» — это результирующий Zip-файл, «testfile» — это имя содержимого, которое передается в команду.

Результат от unzip -l test.zip

Archive:  test.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        6  01-07-2010 12:56   testfile
---------                     -------
        6                     1 file

А вот рабочий пример с использованием python

echo contents | python -c "import sys
import zipfile
z = zipfile.ZipFile(sys.argv[1],'w')
z.writestr(sys.argv[2],sys.stdin.read())
z.close()
" test5.zip testfile2

Результат unzip -l

Archive:  test5.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        9  01-07-10 13:43   testfile2
 --------                   -------
        9                   1 file

Результат unzip -p

contents
person Peter Lindqvist    schedule 07.01.2010
comment
Спасибо - попробовал, работает отлично! Многие предпочитают делать это, а не сохранять во временные файлы. - person ; 07.01.2010
comment
Решение с именованным каналом от @didier-trosset выглядит более приемлемым, поскольку не требует наличия целого языка программирования + среды выполнения. - person jc00ke; 31.10.2014
comment
@ jc00ke Если вы хотите прочитать комментарии, вы узнаете, что у решения с именованным каналом есть и недостатки. Я также привел пример на двух разных и очень распространенных языках. В большинстве систем Linux есть обе эти среды выполнения. Также есть преимущество в некоторой независимости от платформы. - person Peter Lindqvist; 06.11.2014
comment
Аккуратно, но кажется, что он считывает весь файл в память, поэтому может быть проблемой для большого файла. Решение @azenet позволяет избежать этого. - person AdamS; 05.10.2018

Ты можешь это сделать.

ls | zip test.zip -@

это делается исходя из того, что у меня есть 3 файла в каталоге.

-rw-rw-r-- 1 xxx domain users   6 Jan  7 11:41 test1.txt
-rw-rw-r-- 1 xxx domain users   6 Jan  7 11:41 test2.txt
-rw-rw-r-- 1 xxx domain users   6 Jan  7 11:41 test3.txt

и сам файл, результат то

Archive:  test.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        6  01-07-10 11:41   test1.txt
        6  01-07-10 11:41   test2.txt
        6  01-07-10 11:41   test3.txt
 --------                   -------
       18                   3 files

Со страницы Linux Zip Man

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

person Arto Uusikangas    schedule 07.01.2010
comment
Спасибо - это работает, когда передается несколько файлов, но в этой ситуации я передаю содержимое файла (в этом случае результаты MySQL с разделителями табуляции). Zip достаточно умен, чтобы обращаться с ним как с файлом, но мне нужно знать, как указать ему, как называть это содержимое внутри созданного им zip-файла. - person ; 07.01.2010
comment
Итак, если я вас правильно понял, вы хотите, чтобы в zip-файле был 1 файл со всем содержимым из вашего соответствия sql? - person Arto Uusikangas; 07.01.2010
comment
Возможно, это не то, что хотел ОП, но это именно то, что мне было нужно :) - person zelanix; 27.11.2014

Вы можете использовать именованный канал и отправлять в него выходные данные запроса при архивации из него.

mkfifo output.txt ; mysql [params and query] > output.txt & zip output.zip -FI output.txt ; rm output.txt
person Didier Trosset    schedule 07.01.2010
comment
Спасибо, это почти работает: использование & zip создает неполный файл; кажется, что zip работает, пока еще не все данные были сброшены в именованный канал. Если я использую ; zip, то все хорошо. - person Jens; 04.11.2012
comment
Проблема с использованием ; zip заключается в том, что он будет ждать завершения команды mysql, прежде чем начать чтение из именованного канала. Именованные каналы не имеют бесконечной емкости. Однако, если содержимое не очень большое, проблем быть не должно. - person Didier Trosset; 09.11.2012

Я не мог справиться с ответом PHP (недостаточно памяти на больших дампах mysql), и FIFO не работал как Я хотел, поэтому мое решение состоит в том, чтобы переименовать файл внутри ZIP-архива после запуска дампа, используя zipnote (который включен в zip-пакет в Debian).

mysql [params and query] | zip -q output.zip -
echo -e "@ -\n@=newname.sql" | zipnote -w output.zip
person azenet    schedule 21.12.2016
comment
Имейте в виду, что zipnote не редактирует файл на месте, а создает новый временный файл для каждого вызова. Это может быть связано с тем, что на вашем носителе недостаточно места для двух файлов такого размера, или если вы добавляете множество файлов таким образом и переименовываете каждый по мере продвижения (таким образом перестраивая весь архив для каждого добавления). - person Walf; 17.06.2020

mysql [params and query] | python3 -c "import sys as s,os,zipfile as m;z=m.ZipFile(os.fdopen(s.stdout.fileno(),'wb'),'w');z.writestr(s.argv[1],s.stdin.read());z.close()" 'filename.sql' > output.zip

В Python 3.5 добавлена ​​поддержка записи в недоступные для поиска потоки.

Это не красиво, но работает.

person 166_MMX    schedule 21.05.2019

Можешь попробовать:

mysql [params and query] | zip -q output.zip -@
person ghostdog74    schedule 07.01.2010
comment
нет, это не сработает, -@ берет список имен файлов из стандартного ввода, поэтому вывод mysql будет интерпретироваться как список файлов. - person reox; 14.05.2014