Podziel wszystkie pliki PDF na katalog, zachowując strukturę katalogów

11

Próbuję utworzyć skompresowany plik tar, który zawiera wszystkie pliki PDF, które istnieją w jednym z moich katalogów. Struktura katalogu musi zostać zachowana. Puste katalogi nie są potrzebne, ale tak naprawdę nie obchodzi mnie, czy tam są.

Załóżmy na przykład, że miałem katalog, który wyglądał tak:

dir
dir/subdir1
dir/subdir1/subsubdir1/song.mp3
dir/subdir2
dir/subdir2/subsubdir1
dir/subdir2/subsubdir1/document.pdf
dir/subdir2/subsubdir1/another-song.mp3
dir/subdir2/subsubdir1/top-ten-movies.txt
dir/subdir3
dir/subdir3/another-document.pdf

Po uruchomieniu polecenia chciałbym mieć dir.tar.gzto:

dir
dir/subdir2
dir/subdir2/subsubdir1
dir/subdir2/subsubdir1/document.pdf
dir/subdir3
dir/subdir3/another-document.pdf

Możliwy?

Matt Alexander
źródło

Odpowiedzi:

10

Spowoduje to wyświetlenie wszystkich plików PDF:

$ find dir/ -name '*.pdf'
./dir/subdir2/subsubdir1/document.pdf
./dir/subdir3/another-document.pdf

Możesz potokować to, aby xargsuzyskać go jako pojedynczą linię rozdzielaną spacjami, i podać to, taraby utworzyć archiwum:

$ find dir/ -name '*.pdf' | xargs tar czf dir.tar.gz

(W ten sposób pomija się puste katalogi)

Michał Mrożek
źródło
1
To niesamowite, dziękuję za pomoc. Oto, co wymyśliłem:find docs \( -iname '*.pdf' -o -iname '*.mp3' \) -printf '"%p"\n' | xargs tar czf docs-media.tar.gz
Matt Alexander
3
@mattalexx: Uwaga: to polecenie nie będzie działać, jeśli którakolwiek z nazw plików zawiera spacje lub \'"(błąd xargs) i nie będzie działać, jeśli jest zbyt wiele nazw plików (błąd jądra).
Gilles „SO - przestań być zły”,
2
@Gilles Jeśli chodzi o nazwy plików ze spacjami i pojedynczymi cudzysłowami, ta -printf '"%p"\n'część się tym zajmuje (przynajmniej dla mnie).
Matt Alexander
1
@Gilles Ciekawe na temat ograniczenia jądra. Ile argumentów możesz mieć w poleceniu w systemie Linux?
Matt Alexander
5
Och, w „nie zadziała”, zauważ, że trybem awarii jest tutaj, że jeśli linia poleceń jest zbyt długa, xargs podzieli ją, tak że ostatnie wywołanie tar spowoduje ciche nadpisanie plików zapisanych przez poprzednie wywołania .
Gilles „SO- przestań być zły”,
6

Z bash ≥4 lub zsh i GNU tar:

tar -czf dir.tar.gz dir/**/*.pdf

Może to nie działać, jeśli masz bardzo dużą liczbę plików PDF, a linia poleceń jest zbyt długa. Wtedy potrzebujesz bardziej złożonego rozwiązania opartego na wyszukiwaniu (ponownie, używając GNU tar):

tar -cf dir.tar -T /dev/null
find dir -name '*.pdf' -exec tar -rf dir.tar {} +
gzip dir.tar

Alternatywnie (i przenośnie) możesz utworzyć archiwum za pomocą pax .

pax -w -x ustar -s '/\.pdf$/&/' -s '/.*//' . | gzip >dir.tar.gz

Pierwszy -smówi, aby uwzględnić wszystkie .pdfpliki bez zmiany ich nazwy. Drugi -smówi o zmianie nazwy wszystkich innych plików na pustą nazwę, co w rzeczywistości oznacza, że ​​nie należy uwzględniać ich w archiwum.

Gilles „SO- przestań być zły”
źródło
O tak, chciałem wspomnieć o Zsh **; Nawet nie zdawałem sobie sprawy, że bash 4 miał to teraz
Michael Mrozek