Украсьте все PDF-файлы в каталоге, сохранив структуру каталога

11

Я пытаюсь создать сжатый архив, содержащий все файлы PDF, которые существуют в одном из моих каталогов. Структура каталогов должна быть сохранена. Пустые каталоги не нужны, но мне действительно все равно, если они там есть.

Например, скажем, у меня был каталог, который выглядел так:

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

После запуска команды я хотел бы dir.tar.gzсодержать это:

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

Возможный?

Мэтт Александр
источник

Ответы:

10

Это перечислит все файлы PDF:

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

Вы можете передать это, чтобы xargsполучить в виде одной строки, разделенной пробелами, и передать это tarдля создания архива:

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

(Таким образом пропускаются пустые каталоги)

Михаил Мрозек
источник
1
Это так здорово, спасибо за помощь. Вот что я придумала:find docs \( -iname '*.pdf' -o -iname '*.mp3' \) -printf '"%p"\n' | xargs tar czf docs-media.tar.gz
Мэтт Александр
3
@mattalexx: Помните, что эта команда не будет работать, если любое из имен файлов содержит пробелы или \'"(ошибка xargs), и не будет работать, если слишком много имен файлов (ошибка ядра).
Жиль "ТАК ... перестать быть злым"
2
@Gilles Что касается имен файлов с пробелами и одинарными кавычками, об этом -printf '"%p"\n'позаботится часть (по крайней мере, для меня).
Мэтт Александр
1
@Gilles Интересно об ограничении ядра. Сколько аргументов вы можете иметь в команде в Linux?
Мэтт Александр
5
О, что касается «не будет работать», обратите внимание, что режим сбоя здесь заключается в том, что, если командная строка слишком длинная, xargs разделит ее, так что последний вызов tar автоматически перезапишет файлы, записанные предыдущими вызовами .
Жиль "ТАК - перестань быть злым"
6

С bash ≥4 или zsh и GNU tar:

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

Это может не сработать, если у вас очень большое количество PDF-файлов и слишком длинная командная строка. Тогда вам понадобится более сложное решение на основе поиска (опять же, с использованием GNU tar):

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

В качестве альтернативы (и переносимо) вы можете создать архив с pax .

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

Первый -sговорит включить все .pdfфайлы, не меняя их имени. Второй -sговорит переименовать все остальные файлы в пустое имя, что фактически означает не включать их в архив.

Жиль "ТАК - прекрати быть злым"
источник
О да, я хотел упомянуть Zsh's **; Я даже не догадывался, что у bash 4 это сейчас есть
Michael Mrozek