tworzenie archiwum przy użyciu tar, w tym wszystkich „plików dot”, ale z wyłączeniem wszystkich podkatalogów i struktury katalogów / wo

18

Chcę wykonać kopię zapasową wszystkich plików „dotfiles” (fe .zshrc) w moim katalogu domowym za pomocą tar , ale z wyłączeniem struktury katalogów i wszystkich podkatalogów.

Próbowałem kilka razy z różnymi poleceniami, ale najlepsze, co osiągnąłem, to archiwum zawierające również ukryte katalogi $HOME.

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

Zastanawiałem się także nad wykorzystaniem findi przesłaniem wyników do tar, ale bez powodzenia. Czy ktoś wie, jak osiągnąć to - z pozoru łatwe - zadanie?

PS: Przez większość czasu, kiedy używam tar do stworzenia archiwum, muszę myśleć o komiksie xkcd:

xkcd 1168 :)

klingt.net
źródło
Odpowiedź sim działa, ale jeśli ktoś otrzymał wyrażenie pasujące tylko do ukrytych plików, opublikuj je!
klingt.net,
1
Z pewnością lepiej byłoby to osiągnąć dzięki swojej skorupie. Rozumiem, że zsh posiada globs że tylko wybrane pliki - *(.)- i myślę, że wyłącza ona .i ..od .*domyślnie (i nie będzie odebrany przez .*(.)tak, ponieważ wybiera tylko pliki). Sam nie używam zsh, więc nie jestem pewien, czy zamienić to w odpowiedź.
evilsoup

Odpowiedzi:

14

Możesz użyć tego polecenia, aby wykonać kopię zapasową wszystkich plików dotfiles ( .<something>) w $HOMEkatalogu:

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

regex używając tylko tar?

metoda nr 1

Badałem to całkiem sporo i wyszedłem pusty. Czynnikiem ograniczającym byłoby to, że podczas tarwykonywania wyklucza, ukośnik końcowy ( /), który pojawia się z katalogami, nie jest częścią równania, gdy tar wykonuje dopasowanie wzorca.

Oto przykład:

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

Ten wariant zawiera wykluczenie .*/i możesz zobaczyć przy włączonym pełnym przełączniku na tar -v, że te katalogi przechodzą przez to wykluczenie.

metoda nr 2

Myślałem, że może przełączniki --no-wildcards-match-slashlub --wildcards-match-slashrozluźnią chciwość tego, .*/ale to też nie miało żadnego efektu.

Usunięcie ukośnika z wykluczenia również .*nie było opcją, ponieważ oznaczałoby tarto wykluczenie wszystkich plików i katalogów dot:

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

metoda nr 3 (brzydka!)

Tak więc jedyną alternatywą, jaką mogę wymyślić, jest podanie listy plików tar. Coś takiego:

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

Takie podejście ma problemy, jeśli liczba plików przekracza maksymalną ilość miejsca na przekazanie argumentów do polecenia, byłby jednym rażącym problemem. Po drugie, jest brzydka i nadmiernie złożona.

więc czego się nauczyliśmy?

Wydaje się, że nie ma prostego i eleganckiego sposobu na osiągnięcie tego za pomocą tarwyrażeń regularnych. Jeśli chodzi o komentarz @ terdon, find ... | tar ...jest to najbardziej odpowiedni sposób na zrobienie tego.

slm
źródło
Naprawdę chciałem to zrobić regex, ale powinienem był wiedzieć, że to nie zadziała :)
klingt.net
@ klingt.net - powinno być możliwe, szukam teraz.
slm
@ klingt.net dlaczego wolisz bardziej skomplikowany sposób? Podczas korzystania regexprawdopodobnie będziesz musiał uciec przed wiodącą kropką i będziesz miał problemy z ignorowaniem .i ... Jestem pewien, że jest to możliwe, ponieważ slm prawdopodobnie pokaże, ale nie rozumiem, dlaczego warto.
terdon
1
@ klingt.net - wszystko, co findznajdzie polecenie, jest przekazywane jako argument tar. {}Mówi gdzie chcesz te wyniki, aby przejść do odpowiedniego -execpolecenia. +Mówi dodać tyle wynikami findile się zmieści w wierszu poleceń i wywołać tartylko kilka razy, zamiast za każdym razem wynik został znaleziony.
slm
1
@ klingt.net - nie ma sposobu na osiągnięcie tego za pomocą regexi tarponieważ nie ma sposobu na wyizolowanie katalogów kropek ( .blah/). Tar nie używa ukośnika końcowego podczas wyłączania.
slm
4

Ten rodzaj kontroli nad dopasowanymi plikami jest poza strefą komfortu tar. Zasady dopasowywania plików są ograniczone do prostych dopasowań nad nazwami.

find jest jeden sposób, ale skoro masz Zsh, masz łatwiej:

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

To .w nawiasach na końcu wyrażenia wieloznacznego to kwalifikator glob, który mówi „dopasowuj tylko zwykłe pliki”.

Dowiązania symboliczne do zwykłych plików nie są dopasowane. Jeśli zmienisz na .*(-.), zostaną one uwzględnione, ale plik nie trafi do archiwum, chyba że zostanie również dołączony. Jeśli chcesz zastąpić dowiązanie symboliczne ich celami, zrób to .*(-.:A):Adodaje modyfikator rozszerzenia historii, który rozwiązuje wszystkie dowiązania symboliczne do ścieżki, która nie używa dowiązań symbolicznych.

Gilles „SO- przestań być zły”
źródło
3

Ta odpowiedź jest oparta na slm, ale pokażę też, jak dołączyć katalogi zaczynające się od .

Aby skompresować pliki kropek w katalogu domowym:

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

Aby uwzględnić katalogi:

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

Opcja ?jest opcjonalna w pierwszym poleceniu, ale nie w drugim, w przeciwnym razie findbędzie zawierać .katalog (bieżący).

sudoman
źródło
1

co powiesz na:

tar -C $HOME -cvzf dotfiles.tgz .
anonim
źródło