Как выловить фиксированный неизвестный номер файла? - PullRequest
0 голосов
/ 06 июня 2019

Я работаю над мини-проектом, в котором я заархивировал логи, отображаемые следующим образом:

youyou.log
youyou.log.1.gz
youyou.log.2.gz
youyou.log.3.gz

Где я должен их распаковать, затем объединить их с самым высоким индексом в youyou.log

Дело в том, что иногда у меня мог быть только один файл, иногда больше, но неизвестно, что он может идти до youyou.log.n.gz

Я начал писать что-то, кто работает, но это совсем не элегантно. Я принял фиксированное количество файлов .gz и выдает ошибку, которую позже проигнорировал.

main.sh    
#!/bin/bash

gunzip *.gz 
cat youyou.log.7 youyou.log.6 youyou.log.5 youyou.log.4 youyou.log.3 .log.2 youyou.log.1 youyou.log > youyou_complete.log 

затем игнорируется так:

 main.sh  > /dev/null 2>&1

Есть ли лучший способ справиться с этим, пожалуйста? Спасибо

Ответы [ 4 ]

1 голос
/ 06 июня 2019

Пожалуйста, попробуйте следующее:

find . -name "youyou.log.*.gz" -maxdepth 1 | sort -rn -t. -k4 | xargs zcat | cat - youyou.log > youyou_complete.log

Предполагается, что вы не распаковываете файлы *.gz заранее.

[Пояснения]

  • find . -name "youyou.log.*.gz" -maxdepth 1 находит файлы с указанным шаблоном в текущем каталоге, затем создает список, такой как:

    ./youyou.log.1.gz
    ./youyou.log.2.gz
    ./youyou.log.3.gz
    [snip]
    ./youyou.log.9.gz
    ./youyou.log.10.gz
    
  • sort -rn -t. -k4 сначала разделяет переданные имена файлов на ".", Затем внутренний список будет выглядеть примерно так:

    (null)  /youyou  log  1  gz
    (null)  /youyou  log  2  gz
    (null)  /youyou  log  3  gz
    [snip]
    (null)  /youyou  log  9  gz
    (null)  /youyou  log  10 gz
    
  • Опция -k4 указывает sort отсортировать список имен файлов по 4-му столбцу (1, 2, 3, ..).Параметр -n указывает числовую сортировку, а параметр -r инвертирует результат сравнения.

  • Теперь следующий список отправляется на стандартный ввод команды xargs:

    ./youyou.log.10.gz
    ./youyou.log.9.gz
    [snip]
    ./youyou.log.3.gz
    ./youyou.log.2.gz
    ./youyou.log.1.gz
    
  • xargs создает команду, которая состоит из аргумента (ов), за которым следуют аргументы, считанные из стандартного ввода.Тогда команда будет выглядеть следующим образом:

    zcat ./youyou.log.10.gz ./youyou.log.9.gz ... ./youyou.log.1.gz 
    
  • zcat распаковывает список файлов и записывает несжатые данные на стандартный вывод путем слияния данных в порядке аргументов.

  • Последняя команда cat - youyou.log объединяет стандартный ввод и youyou.log в указанном порядке, а затем перенаправляет результат в youyou_complete.log.

Если вашsort поддерживает параметр -z, лучше будет сказать:

find . -name "youyou.log.*.gz" -maxdepth 1 -print0 | sort -z -rn -t. -k4 | xargs -0 zcat | cat - youyou.log > youyou_complete.log
  • -print0 параметр говорит find использовать нулевой символ \0 в качестве разделителя спискаимен файлов вместо новых строк.Опция -z для sort и опция -0 для xargs взаимодействуют с ним.
    Если имена файлов содержат пробелы или символы новой строки, xargs неправильно разделяет список аргументов на них.В приведенных примерах этого может не произойти, поскольку имена файлов, очевидно, не содержат пробелов, но такое соображение может быть полезно для обеспечения безопасности сценария и его будущего использования (IMHO).
0 голосов
/ 06 июня 2019
touch tmp.log
gzip -c tmp.log > tmp.log.gz

for i in $(dir -r *.gz); do
  cat $i >> tmp.log.gz
done

gunzip tmp.gz

cat youyou.log >> tmp.log

Я еще не тестировал его, хотя сам код может быть понятен.

единственное, о чем я беспокоюсь, это то, что .gz порядок вывода dir, если у вас есть файл журнала с именем youyou.log.11, youyou.log.22 и т. Д.

0 голосов
/ 06 июня 2019

Сложная задача - получить файлы в порядке убывания, и ваша спецификация немного неясна, что вы подразумеваете под этим. Например, если у вас есть youyou.log.32 и youyou.log.4 - какой из них должен стоять первым? Если вас интересует строгий порядок символов, вы можете использовать ls, чтобы получить правильно отсортированный список (со всеми подводными камнями ls), т.е.

# bash
cat $(ls -r youyou.log.[0-9]*) >youyou.complete.log

или вы можете переключиться с bash на zsh, где генерация файла может быть выполнена с помощью сортировки. Пример:

# zsh
cat youyou.log.[0-9]*(On) >youyou.complete.log

Сортировка (On) по убыванию по названию. Это отсортировало бы youyou.log.32 после youyou.log.4. Если вы можете организовать, чтобы файлы журналов имели подходящую временную метку, использование (Om) вместо (On) приведет к сортировке по убыванию по времени модификации.

Если у вас нет метки времени, но вы хотите отсортировать файлы «по номерам», то есть youyou.log.32 раньше, чем youyou.log.4, потому что 4 меньше 32, лучшее решение, которое я могу придумать будет использовать sort:

# bash
cat $(echo youyou.log.[0-9]*|fmt -w 1|sort -n -r -t. -k 3) >youyou.complete.log

fmt гарантирует, что у нас есть один файл youyou на строку, а sort сортирует численно (-n) в 3-м поле (-k 3), где разделитель полей представляет собой период (-т.).

0 голосов
/ 06 июня 2019

Вот пример использования Python

import os
path = "/home/user/logs/"
listOfFiles = os.listdir(path)
mainFile = open("youyou.log.complete", "a")
for file in listOfFiles:
    os.system("gunzip ", file)
listOfUnzipped = os.listdir(path)
for file in listOfUnzipped:
    secondaryFile = open(file, "r")
    text = secondaryFile.read()
    mainFile.write(text)
    mainFile.write("\r\n")
    secondaryFile.close()
mainFile.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...