У меня есть структура каталогов, которая выглядит так:
main_directory/
directory1:
sub_directory1:
files:
myfile.txt
otherfile.txt
sub_directory2:
files:
myfile.txt
otherfile.txt
sub_directory3:
files:
myfile.txt
otherfile.txt
sub_directory4:
files:
myfile.txt
otherfile.txt
directory2:
sub_directory1:
files:
myfile.txt
otherfile.txt
sub_directory2:
files:
myfile.txt
otherfile.txt
sub_directory3:
files:
myfile.txt
otherfile.txt
sub_directory4:
files:
myfile.txt
otherfile.txt
Я пытаюсь выяснить (методом проб и ошибок, потому что я не эксперт в Linux), как сжимать только файлы myfile.txt
во всех каталогах. Поскольку все они имеют одно и то же имя файла и разные пути (обойти это было невозможно), мне также нужно сохранить путь к файлам в архиве. Итак, окончательный архивный файл tar, который я хочу создать, будет иметь следующее содержимое:
mytar.tar.gz
main_directory/directory1/sub_directory1/files/myfile.txt
main_directory/directory1/sub_directory2/files/myfile.txt
main_directory/directory1/sub_directory3/files/myfile.txt
main_directory/directory1/sub_directory4/files/myfile.txt
main_directory/directory2/sub_directory1/files/myfile.txt
main_directory/directory3/sub_directory2/files/myfile.txt
main_directory/directory4/sub_directory3/files/myfile.txt
main_directory/directory5/sub_directory4/files/myfile.txt
Есть ли простой способ bash
сделать это? Полагаю, я мог бы написать для этого сценарий python
, но это кажется излишним.
Есть ли у кого-нибудь совет?
4 ответа
Это преодолело эту проблему, описанную в другом ответе.
find main_directory/ -name "myfile.txt" | tar -czvf mytar.tar.gz -T -
Предполагая, что файлов не так много, вы можете сделать что-то вроде:
cd main_directory/..
find main_directory -name "myfile.txt" | xargs tar zcf mytar.tar.gz
Если файлов много, вы можете передать список файлов в файл / поток и передать его в tar.
find main_directory -name "myfile.txt" -print0 | tar zcf myar.tar.gz --null -T -
Это распечатывает имена файлов, разделенные нулями (от -print0
до find
), и инструктирует tar
правильно проанализировать это из stdin
; использование нулей гарантирует, что любые специальные символы в каталогах обрабатываются правильно
С достаточно новой (я полагаю, 4.0.0+) версией bash (и ряда других оболочек) будет работать следующее:
tar -czf mytar.tar.gz main_directory/**/myfile.txt
globstar
(и dotglob
) включено, но все равно будет срабатывать ARG_MAX
и не работать с большим количеством файлов.
globstar
, но забыл. И да, проблемы с длиной командной строки по-прежнему будут проблемой, но сбой здесь не такой серьезный, как в случае с @EmilSit, поскольку он не заканчивается усеченным (но, по-видимому, полным) tar-архивом (или ошибкой глубоко в процесс tar) и вместо этого сразу же появляются ошибки.
Если структура каталогов действительно такая регулярная, подстановочный знак
main_directory/*/*/files/myfile.txt
Будет соответствовать нужным файлам. Однако, если файлов много, вам может потребоваться вернуться к find
/ xargs
, чтобы избежать проблемы "слишком длинный список аргументов" (ARG_MAX
).
Если есть файлы с именем myfile.txt
, которые вы не хотите включать, потому что их путь не соответствует в точности подстановочному знаку, безусловно, есть способы исключить их и из find
; возможно, тогда это дополнительное ограничение следует указать в вопросе.
Похожие вопросы
Новые вопросы
linux
ВНИМАНИЕ: Все вопросы по Linux должны быть связаны с программированием; те, которые не будут закрыты. Используйте этот тег, только если ваш вопрос касается программирования с использованием API-интерфейсов Linux или поведения, специфичного для Linux, а не только потому, что вы запускаете свой код в Linux. Если вам нужна поддержка Linux, вы можете попробовать https://unix.stackexchange.com или сайт Stack Exchange конкретного дистрибутива Linux, например https://askubuntu.com или https://elementaryos.stackexchange.com/.
tar
несколько раз и перезаписывать себя (или терпеть неудачу). Возможно, было бы лучше использовать аргумент-T
для tar, чтобы указать ему получить список файлов для архивирования из файла и указать использовать/dev/stdin
или аналогичный (или просто записать в файл, а затем передайте этоtar
.-T
; обновил мой ответ, включив в него это, а также трюк с обработкой новой строки, нулей или других специальных символов в именах файлов.