Есть ли у unzip способ извлечь только конкретную подпапку, не создавая родительские директории этой папки?

Вопрос или проблема

Мне нужно извлечь конкретную подпапку (и все ее содержимое) из .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 не предоставляет прямого способа выполнения такой задачи.

Решение через фильтрацию и цикл

Для достижения желаемого результата – извлечения только содержимого подпапки без ее родительских директорий – можно воспользоваться следующими шагами:

  1. Получить список файлов: Для начала, вы можете использовать команду unzip -l, чтобы получить список всех файлов в архиве. Этот список можно отфильтровать при помощи инструмента grep, чтобы оставить только те файлы, которые находятся в интересующей вас подпапке.

    unzip -l /path/to/archive.zip | grep 'var/www/html/example.com/'
  2. Извлечение файлов по отдельности: После этого можно написать цикл, который будет извлекать каждый файл из полученного списка. Важно будет использовать опцию -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 и циклов, или же просто перемещая файлы после извлечения, вы сможете добиться желаемого результата. Важно помнить, что каждое из предложенных решений имеет свои плюсы и минусы, и выбор метода будет зависеть от конкретной задачи и ваших предпочтений.

Оцените материал
Добавить комментарий

Капча загружается...