Вопрос или проблема
Мне нужно извлечь конкретную подпапку (и все ее содержимое) из .zip с помощью стандартного инструмента unzip
. Я не заинтересован в его родительских каталогах и не хочу, чтобы они создавались.
Например:
unzip /path/to/archive.zip "var/www/html/example.com/*" -d ~/website
Я хотел бы, чтобы папка ~/website
содержала только содержимое example.com
из архива, но на самом деле unzip воссоздает путь к родительскому каталогу, так что в итоге у меня получается ~/website/var/www/html/example.com
.
Я видел этот вопрос о том, как извлечь конкретную папку, но он не ответил на данный вопрос.
Нет, это не функция, которую имеет unzip
. (Мне просто пришлось прочитать man unzip
, чтобы проверить, вам тоже стоит это сделать!)
Вы можете вызвать unzip с -l
, чтобы сначала получить список файлов внутри архива, отфильтровать их с помощью grep
для нужной подпапки, а затем пройтись по результату, чтобы вызвать unzip
, чтобы извлечь каждый отдельный файл с опцией -c
, чтобы выводить их на stdout и записывать в целевую директорию так, как вы хотели.
Либо, знаете, можно сделать один mv
после извлечения.
Ответ или решение
Извлечение конкретной подпапки из архива ZIP, не создавая при этом родительские директории, является распространенной задачей среди пользователей системы Unix. Используя стандартную утилиту unzip
, эта задача может вызвать некоторые трудности, поскольку unzip
по умолчанию восстанавливает полную структуру каталогов, что может привести к нежелательным результатам.
Проблема извлечения с помощью unzip
При выполнении команды, подобной следующей:
unzip /path/to/archive.zip "var/www/html/example.com/*" -d ~/website
вы получаете структуру каталогов:
~/website/var/www/html/example.com
Этого можно избежать при помощи нескольких альтернативных подходов, однако, к сожалению, команда unzip
не предоставляет прямого способа выполнения такой задачи.
Решение через фильтрацию и цикл
Для достижения желаемого результата – извлечения только содержимого подпапки без ее родительских директорий – можно воспользоваться следующими шагами:
-
Получить список файлов: Для начала, вы можете использовать команду
unzip -l
, чтобы получить список всех файлов в архиве. Этот список можно отфильтровать при помощи инструментаgrep
, чтобы оставить только те файлы, которые находятся в интересующей вас подпапке.unzip -l /path/to/archive.zip | grep 'var/www/html/example.com/'
-
Извлечение файлов по отдельности: После этого можно написать цикл, который будет извлекать каждый файл из полученного списка. Важно будет использовать опцию
-c
, чтобы выводить содержимое каждого файла на стандартный вывод, а затем перенаправлять его в желаемую директорию.Пример скрипта:
for file in $(unzip -l /path/to/archive.zip | grep 'var/www/html/example.com/' | awk '{print $NF}'); do unzip -c /path/to/archive.zip "$file" > ~/website/$(basename "$file") done
Обратите внимание, что
$(basename "$file")
берёт только имя файла без пути, так чтобы сохранить ровно ту структуру каталогов, которая вам нужна.
Использование mv после извлечения
Альтернативный, более простой, но менее элегантный способ – это просто выполнить извлечение с unzip
, а затем переместить полученные файлы в нужную директорию. Например:
unzip /path/to/archive.zip -d ~/website
mv ~/website/var/www/html/example.com/* ~/website/
После этого вы можете удалить из директории ~/website
ненужные каталоги:
rm -r ~/website/var ~/website/www ~/website/html
Заключение
Таким образом, хотя утилита unzip
не поддерживает прямое извлечение подпапок без родительских директорий, существует несколько обходных решений. Используя комбинацию команд unzip
, grep
и циклов, или же просто перемещая файлы после извлечения, вы сможете добиться желаемого результата. Важно помнить, что каждое из предложенных решений имеет свои плюсы и минусы, и выбор метода будет зависеть от конкретной задачи и ваших предпочтений.