створення архіву за допомогою tar, включаючи всі "dotfiles", але виключаючи всі підкаталоги та / wo структуру каталогів


18

Я хочу створити резервну копію всіх "dotfiles" (fe .zshrc) у своєму домашньому каталозі з tar , але виключаючи структуру каталогів та всі підкаталоги.

Я декілька разів пробував це з різними командами, але найкраще, що я досяг, - це архів, до якого входили також приховані каталоги $HOME.

#!/bin/zsh
BACKUPFILE=dotfile_backup.tar.gz
tar --create --file=$HOME/$BACKUPFILE --auto-compress --no-recursion --exclude=. --exclude=.. --exclude=*/ --directory=$HOME .*

Я також думав про те, щоб скористатись findрезультатом та тартами, але не пощастило. Хтось знає, як досягти цього - здавалося б, легкого - завдання?

PS: Більшість випадків, коли я використовую tar для створення архіву, мені доводиться думати про xkcd comic:

xkcd 1168 :)


Відповідь sim працює, але якщо хтось отримав регулярний вираз, який відповідає лише прихованим файлам, будь ласка, опублікуйте його!
klingt.net

1
Звичайно, це було б краще досягти вашою оболонкою. Я розумію , що ЗШ має кульки , які вибирають тільки файли - *(.)- і я думаю , що це виключає .і ..від .*за замовчуванням (і вони не будуть підхоплені в .*(.)будь-якому випадку, так як він вибирає тільки файли). Я сам не використовую zsh, тому не впевнений, щоб перетворити це на відповідь.
злий

Відповіді:


14

Ви можете використовувати цю команду для резервного копіювання всіх точок файлів ( .<something>) у вашому $HOMEкаталозі:

$ cd ~
$ find . -maxdepth 1 -type f -name ".*" -exec tar zcvf dotfiles.tar.gz {} +

регекс за допомогою просто дьогтю?

метод №1

Я дослідив це зовсім небагато і вийшов порожнім. Обмежуючим фактором було б те, що при tarйого виконанні виключається, косою косою рисою ( /), яка відображається з каталогами, не є частиною рівняння, коли tar виконує відповідність шаблону.

Ось приклад:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --exclude={'.','..','.*/'} .*
.qalculate/
.qt/
.qterm/
.qtoctave/
.RapidSVN
.RData
.Rhistory

Цей варіант включає виключення, .*/і ви можете переконатись, що перемикач багатослідового вмикання на tar -v, що ці каталоги проходять через це виключення.

метод №2

Я думав, що, можливо, комутатори --no-wildcards-match-slashабо --wildcards-match-slashпослаблять жадібність, .*/але це також не вплинуло.

Знімання косої риски виключити .*не було також варіантом, оскільки це дозволило б tarвиключити всі dotfiles та dotdirectories:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --exclude={'.','..','.*'} .*
$

метод №3 (некрасиво!)

Тож єдиною іншою альтернативою, яку я можу уявити, є надання списку файлів tar. Щось на зразок цього:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --wildcards-match-slash --exclude={'.','..','.*/'} $(ls -aF | grep -E "^\..*[^/]$")
.RapidSVN
.RData
.Rhistory

Такий підхід має проблеми, якщо кількість файлів перевищує максимальну кількість місця для передачі аргументів команді буде однією яскравою проблемою. Інша полягає в тому, що це потворно і надмірно складно.

так що ми дізналися?

Здається, не існує прямого та елегантного способу досягти цього, використовуючи tar& регулярні вирази. Що стосується коментаря @ terdon, find ... | tar ...це дійсно більш підходящий спосіб зробити це.


Мені дуже хотілося це зробити regex, але я мав знати, що це не працюватиме так :)
klingt.net

@ klingt.net - це має бути можливо, я зараз дивлюся.
slm

@ klingt.net чому б ти віддав перевагу більш складний спосіб? Використовуючи regexвас, ймовірно, потрібно буде уникнути провідної точки і буде мати проблеми з ігноруванням .та ... Я впевнений, що це можливо, оскільки SLM, ймовірно, продемонструє, але я не розумію, чому це було б вартим.
terdon

1
@ klingt.net - все, що findзнайде команда, передається як аргумент tar. Там, {}де ви хочете, щоб ці результати йшли у відповідній -execкоманді. +Каже , щоб додати стільки ж результатів , findяк буде вписуватися в командному рядку і викликати tarлише пару раз , а не кожного разу , коли результат знайдений.
slm

1
@ klingt.net - немає способу досягти цього за допомогою regexі tarтому, що немає способу виділити крапкові каталоги ( .blah/). Тар не використовує прорізну косу рису під час виключення.
slm

4

Цей тип контролю за відповідними файлами є поза зоною комфорту дьогтю. Її правила узгодження файлів обмежуються простими збігами щодо імен.

find це один із способів, але оскільки у вас є zsh, вам простіше:

tar -cf "$HOME/$BACKUPFILE" --auto-compress .*(.)

У .дужках у кінці виразного символу вираз є глобальним класифікатором, який говорить, що "відповідають лише звичайним файлам".

Символічні посилання на звичайні файли не збігаються. Якщо ви перейдете на .*(-.), вони будуть включені, але файл не потрапить до архіву, якщо він також не включений. Якщо ви хочете замінити символічне посилання на їх цілі, зробіть це .*(-.:A):Aдодає модифікатор розширення історії, який вирішує всі символьні посилання на шлях, який не використовує символічні посилання.


3

Ця відповідь ґрунтується на методі slm, але я також покажу вам, як включати каталоги, починаючи з .

Щоб зібрати файли з крапками у вашому домашньому каталозі:

$ cd
$ find . -maxdepth 1 -type f -name ".?*" -exec tar czfv dotfiles.tgz {} +

Щоб включити каталоги:

$ find . -maxdepth 1 -name ".?*" -exec tar czfv dotfiles.tgz {} +

У ?першій команді необов'язково, але не у другій, інакше findбуде включено .каталог (поточний).


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