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.