tylko pliki tar, bez katalogów

16

Prawdopodobnie mogę napisać skrypt powłoki, aby znaleźć tylko pliki, a następnie przekazać listę do tar, ale zastanawiam się, czy jest już wbudowana funkcja w tar, która pozwala to zrobić w jednym wierszu poleceń?

Na przykład znalazłem --no-recursionprzełącznik, ale kiedy to zrobię:

tar --no-recursion -cvf mydir.tar mydir

Archiwizuje tylko nazwy wpisów w katalogu (w tym podkatalogów!), Ale nie archiwizuje żadnych plików.

Próbowałem także:

 tar --no-recursion -cvf mydir.tar mydir/*

Ale chociaż archiwizuje tylko pliki, archiwizuje także nazwy podkatalogów.

Czy istnieje sposób, aby powiedzieć tylko pliki tar, bez katalogów?

ateiob
źródło
5
Wyjaśnij: czy chcesz stworzyć archiwum o „płaskiej” strukturze (tzn. Wszystkie pliki pomieszane w jednym katalogu)?
rozcietrzewiacz
1
Możesz utworzyć nowy katalog, find mydir -type f |xargs cp -t tempdira następnie tempdir tar.
Kevin,
@rozcietrzewiacz Tak, płaski, ale tylko z tego katalogu, a nie z podkatalogów.
ateiob
1
OK, myślę, że rozumiem, co próbujesz zrobić. Co powiesz nafind mydir -depth 1 -type f | xargs tar cf mydir.tar
Kevin,
2
Ach, spacje. Zastosowanie znalezisko znajduje -exec zamiast: find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +. W +umieszcza wszystkie pliki znajdujące się na tej samej linii poleceń jak xargs.
Kevin

Odpowiedzi:

11

Jak wskazuje camh, poprzednie polecenie miało niewielki problem polegający na tym, że zważywszy na zbyt wiele nazw plików, wykonałoby się więcej niż jeden raz, a późniejsze wywołania cicho wymazały poprzednie uruchomienia. Ponieważ my również nie kompresujemy, możemy nadpisać zamiast zastąpić:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar Avf mydir.tar
find mydir -maxdepth 1 -type f -exec tar Avf mydir.tar {} +

Odpowiedź Iocnarz za korzystania z tar„s --nulli -Topcji działa tak dobrze. Jeśli cpiozainstalowałeś, odpowiedź camh za pomocą tego jest również w porządku. A jeśli masz zshi nie masz nic przeciwko użyciu go do polecenia, odpowiedź Gillesa przy użyciu zsh glob ( *(.)) wydaje się najprostsza.


Kluczem była -maxdepthopcja. Ostateczna odpowiedź, odpowiednio zajmująca się spacjami:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar cvf mydir.tar

Powinno to również działać:

find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +
Kevin
źródło
4
Oba z nich mogą spowodować wielokrotne wywołanie tar. Zarówno z wariantem, jak xargsi findz +maksymalną liczbą argumentów, które można przekazać tarowi. Spowoduje to drugie wywołanie tar zastępujące dane wyjściowe pierwszego.
camh
2
Rozszerzając limit xargs, xargs domyślnie do linii poleceń maksymalnie 128 kB. Jeśli lista plików jest większa, otrzymasz drugie (lub więcej) wywołanie polecenia (tar), co prowadzi do cichej utraty danych. Możesz użyć, -xaby zmusić xargs do awarii zamiast utraty danych, i chociaż jest lepszy niż cichy błąd utraty danych, nadal nie jest idealny. Ten błąd sortowania jest tak niebezpieczny, ponieważ na początku wszystko wydaje się OK, ale gdy lista plików rośnie z czasem, zaczynasz ją uruchamiać i możesz nie zauważyć, dopóki nie spróbujesz przywrócić kopii zapasowej. Potem jest już za późno.
camh
@camh Masz rację, dzięki za zwrócenie na to uwagi; Zaktualizowałem, aby to odzwierciedlić.
Kevin,
1
„Ostateczna odpowiedź” jest nieprawidłowa, jeśli użyjesz „tar c” bez -T, możesz otrzymać częściowe wyniki.
eckes
14

Gdy chcesz korzystać findz tar, najlepszym sposobem jest użycie cpiozamiasttar . cpiopotrafi pisać archiwa tar i jest przeznaczony do pobierania listy plików do archiwizacji ze standardowego wejścia.

find mydir -maxdepth 1 -type f -print0 | cpio -o -H ustar -0 > mydir.tar

Używanie findi cpiojest bardziej uniksowym podejściem, ponieważ pozwalasz finddokonywać wyboru plików z całą mocą, jaką posiada, i pozwalasz cpiona archiwizację. Warto nauczyć się tego prostego użycia cpio, ponieważ łatwo jest rozwiązywać problemy, z którymi walczysz podczas próby tar.

camh
źródło
Znakomity! Użyłem cpio w odległej przeszłości, ale nigdy nie wiedziałem o opcji ustar.
Ian McGowan
2
To działało dla mnie znacznie lepiej niż zaakceptowana odpowiedź.
Dale Anderson
1
tylko nit. -maxdepth 1 powinien pojawić się przed typem f, albo dostaniesz ostrzeżenie z niektórych znalezisk
kdubs
Dzięki @kdubs. Zaktualizowałem odpowiedź, aby umieścić -maxdepthwcześniej -type.
camh
3

Nie jestem pewien, czy rozumiem twoje wymagania. Jeśli chcesz przechowywać zwykłe plikimydir ale nie ich podkatalogi, najłatwiejszym sposobem jest użycie zsh, gdzie dopasowanie tylko zwykłych plików jest prostą sprawą przy użyciu . kwalifikatora glob :

tar cf mydir.tar mydir/*(.)
Gilles „SO- przestań być zły”
źródło
3

Możesz nawet użyć find ... -print0 i tar ... --nullbezpośrednio, bez korzystania xargsw ogóle.

find . -maxdepth 1 -type f -print0 | tar cvf mydir.tar --null -T -

W podanym przykładzie --no-recursion opcja tarto nie jest konieczna, ponieważ przekazywane będą tylko ścieżki plików (a nie katalogów)find celu tar.

Jednak użycie --no-recursionopcji tarw poniższym przykładzie zapobiega tarpodwójnemu archiwizowaniu katalogów. findwykona rekursję drzewa katalogów zamiast tartego.

# compare
find . -print0 | tar cf mydir.tar --null -T -
tar -tf mydir.tar | nl

find . -print0 | tar cf mydir.tar --null --no-recursion -T -
tar -tf mydir.tar | nl
locnarz
źródło
2

Jako akapit wprowadzający w man tar mówi (ostatnie zdanie),

Użycie nazwy katalogu zawsze oznacza, że ​​poniższe podkatalogi powinny zostać uwzględnione w archiwum.

Które rozumiem jako odpowiedź „nie” na twoje pytanie.

rozcietrzewiacz
źródło
Dobry chwyt, oprócz tego, że smoła obejmuje obecnie liczne meachisms wykluczenia (np --no-recursion, --exclude-tagitp). Patrzę, --exclude-tagktóry wygląda obiecująco, ale wydaje się być dokładnym przeciwieństwem tego, czego szukam.
ateiob
Próbowałem tego i zobaczyłem, że postacie są usuwane z długich ścieżek. Używanie tar z -T i --null zgodnie z proponowanym camh pozwoliło uniknąć tego problemu.
Paul Brannan
1
star -c -C startdir -find . ! -type d > out.tar

Pomiń -C startdiri zamień. w startdirrazie powinno pojawić się w archiwum.

Jest to najbardziej wydajna metoda oparta na funkcjach libfind. Libfind oferuje również elementy podstawowe, -chown -chgrp -chmodktóre modyfikują struktury struct i pozwalają na archiwizację różnych metadanych. Działa to również w trybie listy i wypakowywania i pozwala uniknąć rozpakowywania całego archiwum w wielu przypadkach.

schily
źródło
Czy możesz używać -findw -copytrybie. Streszczenie strony podręcznika sugeruje, że możesz, ale nie udało mi się sprawić, by działała (podczas próby odpowiedzi Jak skopiować zmodyfikowane pliki przy zachowaniu struktury folderów ) (ze schily-2016-02-10)
Stéphane Chazelas
Nie testowałem tego przez dłuższy czas. Możliwe, że obecnie występuje błąd. Strona man mówi, że ostatnim argumentem byłby katalog rozpakowywania, ale kiedy spróbuję tego, otrzymuję: „Argumenty ścieżki nie są jeszcze obsługiwane w trybie wypakowywania”. Czy to dostajesz, kiedy próbujesz?
schily
tak. Strona podręcznika mówi również, że możesz znaleźć argumenty tylko po -find, ale jeśli umieszczę katalog docelowy przed -find, również dostanę błąd
Stéphane Chazelas
W procesie wyodrębniania znajduje się kod wyłączający kod znalezienia, a komunikat o błędzie pochodzi z niepoprawnego sprawdzenia, które oczekuje -c, ale powinno również pozwolić na -kopię. W trybie kopiowania analizator składni nie powinien zawierać ostatniego argumentu.
szczęśliwie
1
Ostateczne rozwiązanie zostało teraz opublikowane w narzędziach schily na sourceforge.net/projects/schilytools/files/schily-2016-03-11.tar.bz2, rozwiązuje to również problem z brakującym setlocale () w gwieździe i umożliwia - C katalog dla star -find.
schily,
0

Mógłbym znaleźć rozwiązanie.

find mydir -type f -printf '%P\0'|tar czvf mydir.tar.gz -C mydir --null -T -

Może to być trochę kosztowne, ale i tak będzie działać, ponieważ nie zależy to od xargs.

Ciel
źródło
-1

dir = twój_katalog; cd $ dir; tar -cvf plik.tar `znajdź. -maxdepth 1 -typ f -print`

H Bosch
źródło