Tar каталог, но не храните полные абсолютные пути в архиве


277

У меня есть следующая команда в части резервного сценария оболочки:

tar -cjf site1.bz2 /var/www/site1/

Когда я перечисляю содержимое архива, я получаю:

tar -tf site1.bz2
var/www/site1/style.css
var/www/site1/index.html
var/www/site1/page2.html
var/www/site1/page3.html
var/www/site1/images/img1.png
var/www/site1/images/img2.png
var/www/site1/subdir/index.html

Но я хотел бы удалить часть /var/www/site1из каталогов и имен файлов в архиве, чтобы упростить извлечение и избежать бесполезной постоянной структуры каталогов. Никогда не знаю, на случай, если бы я извлек резервные копии сайтов в месте, где веб-данные не были сохранены /var/www.

Для примера выше, я хотел бы иметь:

tar -tf site1.bz2
style.css
index.html
page2.html
page3.html
images/img1.png
images/img2.png
subdir/index.html

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

Уже есть много вопросов о tar и резервном копировании в stackoverflowи в других местах в сети, но большинство из них просят удалить всю структуру подкаталогов (выравнивание) или просто добавить или удалить начальные / в именах (я не не знаю, что именно меняется при извлечении), но не более.

Прочитав некоторые решения, найденные здесь и там, а также руководство, я попытался:

tar -cjf site1.bz2 -C . /var/www/site1/
tar -cjf site1.bz2 -C / /var/www/site1/
tar -cjf site1.bz2 -C /var/www/site1/ /var/www/site1/
tar -cjf site1.bz2 --strip-components=3 /var/www/site1/

Но никто из них не работал так, как я хочу. Некоторые ничего не делают, другие больше не архивируют подкаталоги.

Он находится внутри скрипта резервного копирования, запущенного Cron, поэтому я не знаю, какой пользователь его запускает, каков путь и текущий каталог, поэтому для всех требуется всегда писать абсолютный путь, и я бы предпочел не менять текущий каталог чтобы не допустить дальнейших ошибок в скрипте (поскольку он не только создает резервные копии веб-сайтов, но и баз данных, а затем отправляет все это на FTP и т. д.)

Как этого добиться?

Я просто неправильно понял, как работает опция -C?



Ну, -Cпросто означает «изменить каталог», в то время как замена пути (или префикса) может быть только сделана --transform. РИФ. superuser.com/questions/595510/prepend-prefix-in-tar/595512 вы можете просто -C (изменить каталог) и --transform его: `` `tar cjf site1.bz2 --transform" s / ^ \. \ // $ targetbase / "-C / var / www / site1. `` `
Даниэле Кручиани

Это очень хороший вопрос, и, к сожалению, ни один из ответов на эту дату не является удовлетворительным. Нам еще предстоит услышать от какого-нибудь мудрого человека, как мы могли бы извлечь только один файл style.css (пример выше) в текущий каталог без какой-либо ссылки на исходное местоположение или дерево каталогов? Я не хочу загромождать мой текущий каталог нежелательной новой древовидной структурой. Звучит как серьезный недостаток тарбола, который игнорировался годами.
elmclose

Ответы:


384
tar -cjf site1.tar.bz2 -C /var/www/site1 .

В приведенном выше примере tar изменится на каталог, /var/www/site1прежде чем делать свое дело, потому что -C /var/www/site1была задана опция .

От man tar:

OTHER OPTIONS

  -C, --directory DIR
       change to directory DIR

152
Не пропустите точку в конце, это важно ;-)
Freedom_Ben

9
Как насчет того, если вы также хотите выбрать файлы для резервного копирования на основе подстановочного знака? -C / var / www / site1 * .dat не работает :(
Энди Лоренц

16
Точка говорит tarархивировать все в текущем каталоге. И -Cустанавливает текущий каталог.
Ларс Бринкгоф,

21
Это прекрасно работает. Я считаю полезным сохранить имя каталога (только не полный путь), поэтому я сделал следующее: tar -czvf site1.tar.gz -C /var/www/ site1(Обратите внимание на пробел, я все еще использую -C, для перехода к родительскому каталогу и указания каталога для tar вместо точки)
Jorfus

9
Я получаю начальную точку на пути tar, например, ./foldersкак это можно удалить?
Mika571

39

Опция -Cработает; просто для пояснения выложу 2 примера:

  1. создание тарбола без полного пути: полный путь /home/testuser/workspace/project/application.warи то, что мы хотим, это просто project/application.warтак:

    tar -cvf output_filename.tar  -C /home/testuser/workspace project

    Примечание: между workspaceи есть пробел project; tar заменит полный путь на just project.

  2. извлечение архива с изменением целевого пути (по умолчанию ., т.е. текущий каталог)

    tar -xvf output_filename.tar -C /home/deploy/

    tarбудет извлекать tarball на основе заданного пути и сохраняя путь создания; в нашем примере файл application.warбудет извлечен в /home/deploy/project/application.war.

    /home/deploy: дано на выписке
    project: дано на создание тарбола

Примечание: если вы хотите поместить созданный тарбол в целевой каталог, вы просто добавляете целевой путь перед именем тарбола. например:

tar -cvf /path/to/place/output_filename.tar  -C /home/testuser/workspace project

1
Как добавить шаблон для выбора файла в последнем примере?
Шива

Проблема с подстановочными знаками заключается в том, что оболочка расширяет их до соответствующих имен файлов и что tar не расширяет их, если они
Герт ван ден Берг

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

14

Кажется, -Cопция upto tar v2.8.3 не работает согласованно на всех платформах (ОС). -CГоворят, что опция добавляет каталог в архив, но в Mac и Ubuntu она добавляет префикс абсолютного пути в сгенерированный файл tar.gz.

tar target_path/file.tar.gz -C source_path/source_dir

Поэтому последовательное и надежное решение заключается cdв том, чтобы войти в source_path (родительский каталог source_dir) и запустить

tar target_path/file.tar.gz source_dir

или

tar -cf target_path/file.tar.gz source_dir

в вашем сценарии. Это удалит префикс абсолютного пути в структуре вашего сгенерированного файла tar.gz.


1
При использовании опции -C DID удаляются префиксы абсолютного пути внутри сгенерированного файла tar.gz в fedora 29. Ваш ответ специфичен для какой-либо системы?
EL_DON

@EL_DON: Я не тестировал опцию -C в Fedora, но в идеале программное обеспечение tar должно работать согласованно на каждой платформе, если только это не ошибка в приложении tar. -C вариант, я тестировал на Mac 10.8 и Mac 10.13 и Ubuntu (версия, которую я не помню). Но, начиная с tar v2.8.3, команда была изменена на tar -cf target_path / file.tar.gz source_dir, и, тем не менее, если вы добавите опцию -C, она не удалит префикс абсолютного пути внутри сгенерированного файла tar.gz.
Чинтхака Сенанаяка

Я снова проверил на системе CentOS. После создания всех путей в примере и запуска команды (с -cvfдобавлением после tar) я обнаружил, что в результирующем файле tar.gz нет абсолютных путей внутри него, что согласуется с некоторыми другими ответами. Если вы считаете, что tar неисправен или устарел в обеих системах, которые я использовал для тестирования, пожалуйста, дайте ссылку на некоторую документацию, которая поддержит ваш ответ. Я думаю, что -Cопция меняет каталог перед выполнением (как в других ответах). Когда я его опускаю, tar пытается добавить нежелательную почту ./, включая пути, начиная с ./.
EL_DON

Я использовал этот документ: linux.die.net/man/1/tar Да, документ говорит, что -C сделает изменение пути, но на моем Mac 10.13 это не работает. это может быть противоречивым поведением tar-приложения. Это означает, что это ошибка. Если вы пишете сценарий оболочки для запуска на всех платформах Unix, тогда лучше быть в безопасности с запуском кода, который будет работать на всех ОС.
Чинтака Сенанаяка

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

7

Следующая команда создаст корневой каталог "." и поместите в него все файлы из указанного каталога.

tar -cjf site1.tar.bz2 -C /var/www/site1 .

Если вы хотите поместить все файлы в корень файла tar, @chinthaka прав. Просто перейдите в каталог и выполните:

tar -cjf target_path/file.tar.gz *

Это поместит все файлы в cwd в файл tar как корневые файлы.


1
Использование * не сохраняет никаких «скрытых» .files или .folders. (fyi, использование -C вместе с * дает сбой, оболочка расширяет текущий
каталог

1

Использование «точки» приводит к созданию папки с именем «точка» (в Ubuntu 16).

tar -tf site1.bz2 -C /var/www/site1/ .

Я рассмотрел это более подробно и подготовил пример. Многострочная запись плюс исключение.

tar -tf site1.bz2\
    -C /var/www/site1/ style.css\
    -C /var/www/site1/ index.html\
    -C /var/www/site1/ page2.html\
    -C /var/www/site1/ page3.html\
    --exclude=images/*.zip\
    -C /var/www/site1/ images/
    -C /var/www/site1/ subdir/
/

Почему вы называете это "точка"? Это просто .текущий каталог. В контексте структуры tar.gz's' это просто базовый / корневой / верхний уровень, верно?
EL_DON

Смотрите снимок для деталей изображения . Мой способ правильнее использовать, это мое мнение.
Сергей Асачев

0

Если вы хотите заархивировать подкаталог и обрезать путь к подкаталогу, эта команда будет полезна:

tar -cjf site1.bz2 -C /var/www/ site1
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.