tar: dodaj wszystkie pliki i katalogi w bieżącym katalogu, W TYM .svn i tak dalej


90

Próbuję tar.gz katalog i używam

tar -czf workspace.tar.gz *

Wynikowy plik tar zawiera .svnkatalogi w podkatalogach, ale NIE w katalogu bieżącym (ponieważ *jest rozwijany tylko do 'widocznych' plików przed przekazaniem do tar

Starałem się

tar -czf workspace.tar.gz .zamiast tego pojawia się błąd, ponieważ „.” zmienił się podczas czytania:

tar: ./workspace.tar.gz: file changed as we read it

Czy istnieje sztuczka, która pozwala *dopasować wszystkie pliki (łącznie z kropkami) w katalogu?

(używając bash w systemie Linux SLES-11 (2.6.27.19)


5
Może to pytanie należy do superużytkownika?
Peter Jaric

Odpowiedzi:


76

Nie twórz pliku tar w katalogu, który pakujesz:

tar -czf /tmp/workspace.tar.gz .

załatwia sprawę, poza tym, że po rozpakowaniu rozpakuje pliki w całym bieżącym katalogu. Lepiej zrobić:

cd ..
tar -czf workspace.tar.gz workspace

lub, jeśli nie znasz nazwy katalogu, w którym byłeś:

base=$(basename $PWD)
cd ..
tar -czf $base.tar.gz $base

(Zakłada się, że nie podążałeś za dowiązaniami symbolicznymi, aby dotrzeć do miejsca, w którym się znajdujesz i że powłoka nie próbuje odgadnąć Cię ponownie, przeskakując wstecz przez łącze symboliczne - bashnie jest godna zaufania pod tym względem. Jeśli musisz się o to martwić, użyj cd -P ..do wykonania fizycznego katalogu zmian. Głupie, że nie jest to domyślne zachowanie w moim odczuciu - mylące przynajmniej dla tych, dla których cd ..nigdy nie miało żadnego innego znaczenia.)


Jeden komentarz w dyskusji mówi:

Muszę [...] wykluczyć katalog główny i [...] muszę umieścić plik tar w katalogu podstawowym.

Pierwsza część komentarza nie ma większego sensu - jeśli plik tar zawiera bieżący katalog, nie zostanie on utworzony podczas wypakowywania pliku z tego archiwum, ponieważ z definicji bieżący katalog już istnieje (z wyjątkiem bardzo dziwnych okoliczności ).

Z drugą częścią komentarza można sobie poradzić na dwa sposoby:

  1. Albo: utwórz plik w innym miejscu - /tmpjest to jedna możliwa lokalizacja - a po zakończeniu przenieś go z powrotem do pierwotnej lokalizacji.
  2. Lub: jeśli używasz GNU Tar, użyj --exclude=workspace.tar.gzopcji. Ciąg po =znaku jest wzorcem - przykład jest najprostszym wzorcem - dokładnym dopasowaniem. Może być konieczne określenie, --exclude=./workspace.tar.gzczy pracujesz w bieżącym katalogu wbrew zaleceniom; może być konieczne określenie, --exclude=workspace/workspace.tar.gzczy przechodzisz o jeden poziom wyżej, zgodnie z sugestią. Jeśli masz wiele plików tar do wykluczenia, użyj „ *”, jak w --exclude=./*.gz.

1
Dobra odpowiedź, ale mam sytuację, w której jestem zmuszony uruchomić to polecenie w katalogu, który ma być spakowany. Nie mam wystarczających uprawnień do uruchamiania go na zewnątrz.
Hexodus

Na pewno idealnym miejscem do spakowania jest / tmp.
Andre Fellows

46

Jeśli naprawdę nie chcesz dołączać głównego katalogu do archiwum tar (a to ogólnie zły pomysł):

tar czf workspace.tar.gz -C /path/to/workspace .

Muszę wykluczyć katalog główny i umieścić plik tar w katalogu podstawowym.
Micha,

@Micha stwórz skrypt bash do zarchiwizowania i skopiowania pliku po
Fedir RYKHTIK

2
Chyba brakuje ci - in -czf.
UpTheCreek

10
man tar: Pierwszy argument tar powinien być funkcją; jedną z liter Acdrtuxlub jedną z długich nazw funkcji. Litera funkcyjna nie musi być poprzedzona prefiksem- i może być łączona z innymi opcjami jednoliterowymi.
rkhayrov

4
Nadal nie działa, nadal mam znak „.” jako główny katalog w moim archiwum
A. Gille

43

Należy wykonać kilka czynności:

  1. Zastąp *, .aby uwzględnić również pliki ukryte.
  2. Aby utworzyć archiwum w tym samym katalogu, --exclude=workspace.tar.gzmożna użyć do wykluczenia samego archiwum.
  3. Aby zapobiec tar: .: file changed as we read itwystąpieniu błędu, gdy archiwum nie zostało jeszcze utworzone, upewnij się, że istnieje (np. Używając touch), więc opcja --exclude pasuje do nazwy pliku archiwum. (Nie pasuje, plik nie istnieje)

W połączeniu daje to następujący skrypt:

touch workspace.tar.gz
tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

7
Czytam wszystkie odpowiedzi i komentarze i jest to najprzyjemniejszy sposób tworzenia archiwum w tym samym katalogu. Z tej odpowiedzi zrozumiałem również, dlaczego występuje ten błąd.
Szymon Sadło

Jeśli chcesz zobaczyć postępy podczas jego kompresji plik tar, można dodać dodatkową flagę --verbose, tak: -czvf.
Mastrianni

18

w katalogu, który chcesz skompresować (bieżący katalog), spróbuj tego:

tar -czf workspace.tar.gz . --exclude=./*.gz

2
Ale teraz narzeka, że ​​plik „.” zmienione podczas czytania. Czy mogę mieć pewność, że uwzględniono wszystkie pliki?
Jaan

1
To wyklucza wszystkie .gzpliki w katalogu.
omerfarukdogan

12

Możesz dołączyć ukryte katalogi, cofając się do katalogu i wykonując:

cd ..
tar czf workspace.tar.gz workspace

Zakładając, że katalog, który chcesz zgzipować, nazywa się obszarem roboczym.


Pozwala to również uniknąć problemu zmiany pliku.
Jonathan Leffler

Nie działa, gdy użytkownik nie ma uprawnień do zapisu w folderze nadrzędnym.
Joachim Wagner

Dokładnie @JoachimWagner!
p01ymath

1
@JoachimWagner. Jeśli nie masz uprawnień do zapisu, zmień je na:tar -czf /path/to/where/you/do/have/permission/workspace.tar.gz workspace
bramp

1
Musiałem wyjąć -przed, czfżeby to zadziałało. W przeciwnym razie otrzymywałem Cannot stat: No such file or directorykomunikat o błędzie.
Phemelo Khetho

6

.Formularz możesz poprawić za pomocą --exclude:

tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

5

Aktualizacja: dodałem poprawkę do komentarza OP.

tar -czf workspace.tar.gz .

rzeczywiście zmieni bieżący katalog, ale dlaczego nie umieścić pliku w innym miejscu?

tar -czf somewhereelse/workspace.tar.gz .
mv somewhereelse/workspace.tar.gz . # Update

Plik zostanie przetworzony później i musi znajdować się w obszarze roboczym - jest trochę brzydki, ale jest po prostu potrzebny (cała sprawa to tylko obejście ...)
Micha

OK, dodam poprawkę :)
Peter Jaric

A jeśli chcesz móc uruchamiać to wielokrotnie, dodaj „rm workspace.tar.gz” przed linią tar.
Peter Jaric,

Jeśli chcesz tarować cały dysk, na tym samym dysku, wygląda na to, że nie masz wielu opcji.
BeeOnRope

4

Właściwie problem dotyczy opcji kompresji. Sztuczka polega na tym, by przesłać wynik smoły do ​​kompresora zamiast korzystać z wbudowanych opcji. Nawiasem mówiąc, może to również zapewnić lepszą kompresję, ponieważ możesz ustawić dodatkowe opcje kompresji.

Minimalna ilość smoły:

tar --exclude=*.tar* -cf workspace.tar .

Podłącz rurkę do wybranej sprężarki. Ten przykład jest rozwlekły i używa xz z maksymalną kompresją:

tar --exclude=*.tar* -cv . | xz -9v >workspace.tar.xz

Rozwiązanie zostało przetestowane na Ubuntu 14.04 i Cygwin pod Windows 7. Jest to odpowiedź wiki społeczności, więc jeśli zauważysz błąd, możesz ją edytować.


Dziękuję Ci! Uratowałem moje życie
Steven

2

Problem z większością przedstawionych tutaj rozwiązań polega na tym, że smoła zawiera się ./na początku każdego wpisu. Tak więc powoduje to posiadanie .katalogu podczas otwierania go przez kompresor GUI. Tak więc skończyłem:

ls -1A | xargs -d "\n" tar cfz my.tar.gz

Jeśli masz już my.tar.gzw bieżącym katalogu, możesz chcieć to grepować:

ls -1A | grep -v my.tar.gz | xargs -d "\n" tar cfz my.tar.gz

Pamiętaj, że xargs ma pewne ograniczenia (zobacz xargs --show-limits). Więc to rozwiązanie nie zadziała, jeśli próbujesz stworzyć pakiet, który ma wiele wpisów (katalogów i plików) w katalogu, który próbujesz tar.


1

Dobre pytanie. W ZSH możesz użyć modyfikatora globbing (D), który oznacza „dotfiles”. Porównać:

ls $HOME/*

i

ls $HOME/*(D)

To poprawnie wyklucza specjalne wpisy katalogu .i ... W Bash możesz użyć, .*aby jawnie dołączyć pliki dotfiles:

ls $HOME/* $HOME/.*

Ale to obejmuje .i ..również, więc nie tego szukałeś. Jestem pewien, że istnieje sposób na tworzenie *dopasowanych plików dotfiles w bashu.


W bashu użyj, .??*aby dopasować wszystkie pliki z kropkami nie .i ... To nie daje plików jednoznakowych (takich jak .a). Aby je również zdobyć, użyj bardziej skomplikowanego .[^.]*.
Scott Minster,

1

Jeszcze inne rozwiązanie, zakładając, że liczba pozycji w folderze nie jest duża:

tar -czf workspace.tar.gz `ls -A`

( ls -Adrukuje zwykłe i ukryte pliki, ale nie „.” i „..”, jak ls -ama to miejsce).


0
tar -czf workspace.tar.gz .??* *

Określenie .??*obejmie pliki i katalogi z „kropką”, które mają co najmniej 2 znaki po kropce. Wadą jest to, że nie będzie zawierał plików / katalogów z pojedynczym znakiem po kropce, na przykład .ajeśli takie istnieją.


0

Jeśli miejsce na dysku nie stanowi problemu, może to być również bardzo łatwe:

mkdir backup
cp -r ./* backup
tar -zcvf backup.tar.gz ./backup

0

Ja miałem podobną sytuację. Myślę, że najlepiej jest utworzyć tar w innym miejscu, a następnie użyć -C, aby poinformować tar o katalogu podstawowym skompresowanych plików. Przykład:

tar -cjf workspace.tar.gz -C <path_to_workspace> $(ls -A <path_to_workspace>)

W ten sposób nie ma potrzeby wykluczania własnego pliku tar. Jak zauważono w innych komentarzach, -A wyświetli listę ukrytych plików.


0

10 lat później masz alternatywę dla tar, zilustrowaną przez Git 2.30 (Q1 2021), który używa " git archive" ( man ) do stworzenia paczki z wydaniem zamiast tar.
(Nie potrzebujesz Git 2.30, aby zastosować tę alternatywę)

Zobacz zobowiązanie 4813277 (11 października 2020 r.) I zobowiązanie 93e7031 (10 października 2020 r.) Autorstwa René Scharfe ( rscharfe) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu 63e5273 , 27 października 2020 r.)

Makefile: użyj git init / add / commit / archive dla dist-doc

Podpisał: René Scharfe

Zredukuj zależność od narzędzi zewnętrznych, generując archiwa dystrybucji dokumentacji HTML i stron podręcznika przy użyciu poleceń ( man ) zamiast tar. Daje to wpisom archiwum te same metadane, co w archiwum dist dla plików binarnych.git

Więc zamiast:

tar cf ../archive.tar .

Możesz to zrobić używając tylko Gita:

git -C workspace init
git -C workspace add .
git -C workspace commit -m workspace
git -C workspace archive --format=tar --prefix=./ HEAD^{tree} > workspace.tar
rm -Rf workspace/.git

Zostało to początkowo zaproponowane, ponieważ, jak wyjaśniono tutaj , niektóre egzotyczne platformy mogą mieć starą dystrybucję tar z brakującymi opcjami.


-1

Używanie findjest prawdopodobnie najłatwiejszym sposobem:

find . -maxdepth 1 -exec tar zcvf workspace.tar.gz {} \+

find . -maxdepth 1znajdzie wszystkie pliki / katalogi / dowiązania symboliczne / etc w bieżącym katalogu i uruchomi polecenie określone przez -exec. W {}poleceniu oznacza , że lista plików idzie tutaj i \+oznacza, że ​​polecenie zostanie uruchomione jako:

tar zcvf workspace.tar.gz .file1 .file2 .dir3

zamiast

tar zcvf workspace.tar.gz .file1
tar zcvf workspace.tar.gz .file2
tar zcvf workspace.tar.gz .dir3

-J jest --xz w podręczniku; w połączeniu z -c to dopiero początek tego, co komputer nazwie „zabawą” :)
Ricalsin

Haha, mój mini-serwer w domu jest bardziej ograniczony przestrzenią dyskową niż procesorem :) Dobra uwaga; Zmienię to, by używał gzip.
Andrew Gunnerson,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.