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

Я хочу сделать резервную копию всех «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 и направить результат на tar, но не повезло. Кто-нибудь знает, как достичь этого – казалось бы, легкой задачи?

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

xkcd 1168 🙂

Вы можете использовать эту команду для резервного копирования всех ваших dotfiles ( .<something> ) в каталоге $HOME :

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

regex, используя только tar?

метод № 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 бы жадность .*/ Но это тоже не повлияло.

Извлечение косой черты из exclude,. .* Не было вариантом, так как это означало бы, что 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 ... find ... | tar ... действительно более подходящий способ сделать это.

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

find один путь, но поскольку у вас есть zsh, вам это проще:

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

Это . в круглых скобках в конце выражения подстановочного символа является квалификатором glob, который говорит «только совпадение с обычными файлами».

Символьные ссылки на обычные файлы не сопоставляются. Если вы измените на .*(-.) , Они будут включены, но файл не попадет в архив, если он не включен. Если вы хотите заменить символическую ссылку своими целями, сделайте это .*(-.:A):A добавляет модификатор расширения истории, который разрешает все символические ссылки на путь, который не использует символические ссылки.

Этот ответ основан на slm's, но я также покажу вам, как включать каталоги, начиная с .

Чтобы закрепить файлы точек в домашнем каталоге:

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

Чтобы включить каталоги:

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

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

как насчет:

 tar -C $HOME -cvzf dotfiles.tgz .