Ознайомте каталог, але не зберігайте повний абсолютний шлях в архіві


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 (змінити каталог) і --перетворити його: `` `tar cjf site1.bz2 --transform" s / ^ \. \ // $ targetbase / "-C / var / www / site1. `` `
Даніеле Крушані

Це дуже гарне запитання, і, на жаль, жодна з відповідей до цієї дати не є задовільною. Ми ще не чуємо від якоїсь мудрої людини, як ми могли витягнути лише один файл style.css (приклад вище) у поточний каталог без будь-яких посилань на початкове місце розташування чи дерево каталогів? Я не хочу захаращувати свій поточний каталог непотрібною новою структурою дерева. Здається, як серйозний недолік тарболу, який ігнорували роками.
elmclose

Відповіді:


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

У наведеному вище прикладі тар зміниться в каталог /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, щоб перейти на батьківський dir та вказати dir to tar замість крапки)
jorfus

9
Я отримую провідну крапку на шляху дьогтю, наприклад, ./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; дьоготь замінить повний шлях на справедливий project.

  2. вилучення тарболу зі зміною цільового шляху (за замовчуванням ., тобто поточний каталог)

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

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

    /home/deploy: дано на витязі
    project: дано на створення тарболу

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

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

1
як додати підстановку для вибору файлу в останньому прикладі?
Сіва

Проблема із символами підкреслення полягає в тому, що оболонка розширює їх до відповідних імен файлів і що дьоготь не розширює їх, якщо вони цитуються ...
Герт ван ден Берг

Я спробував це на Ubuntu 18.04 і не пощастило. Я не впевнений, чого мені не вистачає. Мій stdout відображає його правильно, коли я пакую його, але коли я знімаю його, він все ще має повний шлях
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.
Chinthaka Senanayaka

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

Я використав цей doc: linux.die.net/man/1/tar Так, доктор каже -C змінив би шлях, але на моєму Mac 10.13 він не працює. це може бути непослідовна поведінка програми з дьогтем. Це означає, що це помилка. Якщо ви пишете скрипт оболонки для запуску на всіх платформах unix, тоді будьте в безпеці із запущеним кодом, який буде працювати на всіх ОС.
Chinthaka Senanayaka

Ваша відповідь не говорить про те, що може виникнути помилка, і 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
Використання * не зберігає жодних "прихованих" .файлів чи .folders. (fyi, використовуючи -C разом з * не вдається, оболонка розширює поточний dir, а не -C dir)
Xen2050

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структури Росії це лише базовий / кореневий / верхній рівень, правда?
EL_DON

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

0

Якщо ви хочете архівувати шлях до підкаталогу та обрізати підкаталог, ця команда буде корисною:

tar -cjf site1.bz2 -C /var/www/ site1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.