#shell #tar #archive
Вопрос:
Я пытаюсь извлечь строку из определенного файла .gz в архивированный файл .tar.
Содержимое этого tar
файла содержит архив для каждого хоста, который выглядит примерно так:
APPLOG/cp13ap011/logs/domeus.log.2021-07-09.gz
APPLOG/cp15ap043/logs/domeus.log.2021-07-09.gz
APPLOG/cp14ap411/logs/domeus.log.2021-07-09.gz
APPLOG/cp11ap231/logs/domeus.log.2021-07-09.gz
Я определил местоположение файла
find /backup/tmp/ -type f -name 'APPLOG-P10-2021-07-09.tar' |xargs zgrep -F 'communicationId=6700409965' >> ~/tmp/2021_07_09.txt
Когда я понял, что это файл .tar, содержащий запись в демонстрационных версиях
tar -tf APPLOG-P10-2021-07-09.tar -O |find APPLOG/ -type f -name 'domeus.log.2021-07-09*' | xargs zgrep -E "Id=6700409965" >> ~/tmp/2021_07_09.txt
Файл находится APPLOG/domeus.log.2021-07-09.gz
здесь, есть несколько компьютеров, на которых хранится запись, но все машины будут иметь дублированное имя файла domeus.log.2021-07-09 *, а файл большой, поэтому ему необходимо уточнить строку "Id=6700409965"
В итоге я не получаю результат этих файлов
-rw-r—r— 10 ноября 15 16:58 2021_07_09.txt
Хитрость в том, что я не хочу разархивировать файл, если нет других вариантов
Комментарии:
1.
tar | find
в этом нет никакого смысла.find
не считывает данные из stdin, поэтому он не увидит, что что-либоtar
отправляет его.2. Насколько важно сделать это эффективно? Если это очень важно, я бы использовал другой язык, например Python, где
tarfile
модуль позволяет вам делать все это за один проход. Простые способы сделать это в bash включают чтение вашего входного файла дважды (один раз, чтобы получить доступные имена, один раз, чтобы извлечь содержимое с конкретными именами, которые вас интересуют).3. @CharlesDuffy, я бы с удовольствием это сделал, но у меня едва ли есть доступ, чтобы что-то делать с нашей резервной копией
4. Я не знаю, что вы имеете в виду: у вас нет доступа. Вы имеете в виду, что у вас нет доступного интерпретатора Python? (Это было бы удивительно в современной системе; Python встроен в большинство дистрибутивов Linux уже около 20 лет).
5. @MartinSchapendonk, верно, вопрос в том, имеет ли OP полное имя этого конкретного файла gz перед запуском. (Если бы они это сделали, зачем
find
им вообще использовать?)
Ответ №1:
К сожалению, выполнение этого в bash потребует нескольких проходов — это было бы намного эффективнее в Python, где tarfile
модуль позволяет вам как решать, какие файлы вы хотите проверить, так и читать содержимое этих файлов за один проход.
while IFS= read -r -d '' tarfile; do
tar -xf "$tarfile" -T <(
tar -tf "$tarfile" |
grep -E 'APPLOG/(.*)/logs/domeus[.]log[.]2021-07-09[.]gz'
) -O |
gunzip -c |
grep 'Id=6700409965'
done < <(find /backup/tmp/ -type f -name 'APPLOG-P10-2021-07-09.tar' -print0)
>~/tmp/2021_07_09.txt
Предоставление документации по отдельным используемым методам:
while read
циклы подробно обсуждаются в BashFAQ # 1 .<(...)
синтаксис подстановки процесса — он расширяется до имени файла, из которого...
можно считывать выходные данные, что на современных платформах реализовано с именованным каналом или эквивалентом (так что содержимое не нужно записывать на диск, и процессы могут выполняться параллельно).tar -T
ожидает, что следующим аргументом будет список имен файлов для работы.
Комментарии:
1. tar: для параметра требуется аргумент — ‘C’ Попробуйте ‘tar —help’ или ‘tar —usage’ для получения дополнительной информации. gzip: stdin: неожиданный конец файла
2. Извините, это должно было быть
-O
, а не-C
.3. @Haitham, прошло несколько дней, поэтому мне любопытно, где вы находитесь — если у ваших сотрудников devops был лучший подход, есть ли шанс, что он может появиться в качестве ответа здесь? И вы пробовали повторный запуск после исправления
-O
/-C
thinko ?