mantém o último arquivo de cada mês e exclui o resto

0

Eu tenho arquivos como abaixo. Eu quero manter 30 de setembro, 30 de outubro .... arquivos e excluir o resto.

-rw-r--r-- 1 nbswmcm advboprd 13463761 Sep  2 01:19 vtm_data_12month_20140902.txt
-rw-r--r-- 1 nbswmcm advboprd 13474125 Sep  3 01:51 vtm_data_12month_20140903.txt
-rw-r--r-- 1 nbswmcm advboprd 13492755 Sep  4 01:57 vtm_data_12month_20140904.txt
-rw-r--r-- 1 nbswmcm advboprd 13499981 Sep  5 01:59 vtm_data_12month_20140905.txt
-rw-r--r-- 1 nbswmcm advboprd 13507296 Sep  7 08:39 vtm_data_12month_20140907.txt
-rw-r--r-- 1 nbswmcm advboprd 13508099 Sep  9 04:02 vtm_data_12month_20140909.txt
-rw-r--r-- 1 nbswmcm advboprd 13508886 Sep 10 01:33 vtm_data_12month_20140910.txt
-rw-r--r-- 1 nbswmcm advboprd 13513056 Sep 11 02:25 vtm_data_12month_20140911.txt
-rw-r--r-- 1 nbswmcm advboprd 13512334 Sep 12 02:36 vtm_data_12month_20140912.txt
-rw-r--r-- 1 nbswmcm advboprd 13512391 Sep 14 08:41 vtm_data_12month_20140914.txt
-rw-r--r-- 1 nbswmcm advboprd 13515984 Sep 16 02:35 vtm_data_12month_20140916.txt
-rw-r--r-- 1 nbswmcm advboprd 13516946 Sep 17 02:27 vtm_data_12month_20140917.txt
-rw-r--r-- 1 nbswmcm advboprd 13523528 Sep 18 02:39 vtm_data_12month_20140918.txt
-rw-r--r-- 1 nbswmcm advboprd 13520200 Sep 19 02:28 vtm_data_12month_20140919.txt
-rw-r--r-- 1 nbswmcm advboprd 13514677 Sep 21 09:33 vtm_data_12month_20140921.txt
-rw-r--r-- 1 nbswmcm advboprd 13518239 Sep 23 02:29 vtm_data_12month_20140923.txt
-rw-r--r-- 1 nbswmcm advboprd 13488002 Sep 24 02:51 vtm_data_12month_20140924.txt
-rw-r--r-- 1 nbswmcm advboprd 13491370 Sep 25 02:38 vtm_data_12month_20140925.txt
-rw-r--r-- 1 nbswmcm advboprd 13414606 Sep 26 02:42 vtm_data_12month_20140926.txt
-rw-r--r-- 1 nbswmcm advboprd 13411621 Sep 28 08:59 vtm_data_12month_20140928.txt
-rw-r--r-- 1 nbswmcm advboprd 13529594 Sep 30 02:52 vtm_data_12month_20140930.txt
-rw-r--r-- 1 nbswmcm advboprd 13520560 Oct  1 02:54 vtm_data_12month_20141001.txt
-rw-r--r-- 1 nbswmcm advboprd 13519613 Oct  2 02:54 vtm_data_12month_20141002.txt
-rw-r--r-- 1 nbswmcm advboprd 13534704 Oct  3 02:19 vtm_data_12month_20141003.txt
-rw-r--r-- 1 nbswmcm advboprd 13545015 Oct  5 08:47 vtm_data_12month_20141005.txt
-rw-r--r-- 1 nbswmcm advboprd 13541506 Oct  7 02:51 vtm_data_12month_20141007.txt
-rw-r--r-- 1 nbswmcm advboprd 13556650 Oct  8 02:31 vtm_data_12month_20141008.txt
-rw-r--r-- 1 nbswmcm advboprd 13551903 Oct  9 02:33 vtm_data_12month_20141009.txt
-rw-r--r-- 1 nbswmcm advboprd 13567484 Oct 10 02:33 vtm_data_12month_20141010.txt
-rw-r--r-- 1 nbswmcm advboprd 13569503 Oct 12 08:40 vtm_data_12month_20141012.txt
-rw-r--r-- 1 nbswmcm advboprd 13567657 Oct 14 02:25 vtm_data_12month_20141014.txt
-rw-r--r-- 1 nbswmcm advboprd 13574132 Oct 15 02:40 vtm_data_12month_20141015.txt
-rw-r--r-- 1 nbswmcm advboprd 13581260 Oct 16 02:50 vtm_data_12month_20141016.txt
-rw-r--r-- 1 nbswmcm advboprd 13585758 Oct 17 02:27 vtm_data_12month_20141017.txt
-rw-r--r-- 1 nbswmcm advboprd 13587851 Oct 19 10:02 vtm_data_12month_20141019.txt
-rw-r--r-- 1 nbswmcm advboprd 13591515 Oct 21 02:43 vtm_data_12month_20141021.txt
-rw-r--r-- 1 nbswmcm advboprd 13602271 Oct 22 02:59 vtm_data_12month_20141022.txt
-rw-r--r-- 1 nbswmcm advboprd 13604358 Oct 23 03:22 vtm_data_12month_20141023.txt
-rw-r--r-- 1 nbswmcm advboprd 13607622 Oct 24 02:52 vtm_data_12month_20141024.txt
-rw-r--r-- 1 nbswmcm advboprd 13605666 Oct 26 10:25 vtm_data_12month_20141026.txt
-rw-r--r-- 1 nbswmcm advboprd 13612303 Oct 28 02:32 vtm_data_12month_20141028.txt
-rw-r--r-- 1 nbswmcm advboprd 13617526 Oct 29 02:49 vtm_data_12month_20141029.txt
-rw-r--r-- 1 nbswmcm advboprd 13627963 Oct 30 02:38 vtm_data_12month_20141030.txt
    
por Vamsi Krishna 05.11.2014 / 13:14

4 respostas

2

Em um sistema GNU, com esse padrão de nome de arquivo específico,

ls -r | uniq -w23

daria a você os que manter. Então você pode afastá-los:

ls -r | uniq -w23 | xargs mv -t ../to-keep/

E remova todos os arquivos restantes.

23 é o comprimento de vtm_data_12month_201409 . Portanto, uniq retornaria apenas o primeiro arquivo (na lista de arquivos reversamente ordenada) entre a lista de arquivos com um prefixo idêntico de 23 caracteres.

Para fazer de uma só vez:

ls -r | awk -F_ 'a[substr($NF,1,6)]++'

Isso lista os arquivos a serem removidos.

ls -r | awk -F_ 'a[substr($NF,1,6)]++' | xargs rm -f

(que assume que os nomes dos arquivos não contêm caracteres em branco, citação ou barra invertida).

Aqui, em vez dos 23 primeiros caracteres, observamos os 6 primeiros caracteres após o último caractere _ .

    
por 05.11.2014 / 15:04
2

Use o comando logrotate . Esse é o comando que manipula seus arquivos de log em /var/log . Ele pode girar registros com base na data ou no tamanho.

Veja /etc/cron.daily/logrotate e /etc/logrotate.conf . Você deve ser capaz de colocar uma entrada em /etc/logrotate.conf para manipular o arquivo que deseja girar.

Veja também este site: link

Deixe-me saber se você precisar de mais ajuda. Vou tentar o meu melhor.

OK, no meu sistema /etc/cron.daily/logrotate chama logrotate uma vez por dia. /etc/logrotate.conf informa ao logrotate como lidar com cada arquivo. Então você só precisa se preocupar em modificar /etc/logrotate.conf

Você deve apenas adicionar uma entrada como essa ao seu arquivo /etc/logrotate.conf .

/var/log/LOGFILENAME {
    monthly
    create 0664 root root
    rotate 1
}

Em seguida, reinicie seu sistema ou cron ou faça as alterações entrarem em vigor. Você também pode testar seu arquivo de configuração chamando logrotate diretamente, desta forma:

/usr/sbin/logrotate /etc/logrotate.conf

A linha rotate 1 informa logrotate para manter uma cópia antiga, para que você termine com dois meses de registros: o mês anterior e este mês. Altere rotate 1 para rotate 0 se você quiser manter apenas o registro do mês atual.

    
por 06.11.2014 / 01:37
0

Você precisa resolver esse problema geralmente ou apenas uma vez? Se você só precisa resolvê-lo uma vez, às vezes uma solução simples é melhor. Podemos usar a expansão de chaves no Bash:

rm vtm_data_12month_2014{09,10}{01..29}.txt

Isso pode funcionar no seu caso desde:

  • É improvável que o número de argumentos que enviaremos para rm nos envie por ARG_MAX e
  • O dia em que você quer parar é o mesmo em outubro e setembro.

Se você precisar resolver esse problema de maneira mais geral, precisará levar em consideração o fato de que meses diferentes terminam em dias diferentes (outubro, por exemplo, termina no dia 31, mas seu exemplo só tem dados até o dia 30) .

Se o esquema de nomenclatura de arquivo em seu exemplo puder ser confiável, o seguinte excluirá todos os arquivos, exceto o último, disponível a cada mês (com base no nome do arquivo, não nos carimbos de data e hora reais relacionados à criação ou modificação do arquivo):

get_years() {
  find ./ -type f | cut -d'_' -f4 | cut -c1-4 | sort | uniq
}

get_months_for_year() {
  year=$1
  find ./ -iname "vtm_data_12month_${year}*.txt" -type f | cut -d'_' -f4 | cut -c5-6 | sort | uniq
}

get_latest_for_year_month() {
  year=$1
  month=$2
  find ./ -iname "vtm_data_12month_${year}${month}*.txt" -type f | cut -d'_' -f4 | cut -c7-8 | sort | tail -1
}

for year in $(get_years); do
  for month in $(get_months_for_year $year); do
     latest=$(get_latest_for_year_month $year $month)
     end=$(($latest - 1))
     for i in $(seq 1 $end); do 
      day=$(printf '%02d' $i)
      rm vtm_data_12month_${year}${month}${day}.txt
     done
  done
done

Um idioma diferente do bash que possui uma biblioteca DateTime provavelmente fornecerá uma solução mais parcimoniosa e confiável. Ambas as soluções apresentadas aqui emitirão erros se arquivos para determinados dias estiverem faltando.

    
por 05.11.2014 / 14:05
0

Verificar a validade da data e gerar intervalo de datas é difícil e propenso a erros usando o script bash. A melhor opção seria usar python ou perl ou qualquer outra linguagem de script de nível mais alto que possa fazer verificações em profundidade. Eu atualizei o script para que ele possa excluir arquivos dentro de um intervalo de datas e excluir o intervalo de datas.

As opções serão como

Para excluir arquivos dentro do intervalo

./dfile.py --from 20140929 --to 20141001  --range

Para excluir arquivos fora do intervalo

./dfile.py --from 20140929 --to 20141001  --out-range

Este programa também gera uma mensagem de ajuda útil, pois os argumentos são dados incorretamente.

#!/usr/bin/env python3


import os
import sys
import argparse
import datetime

parser = argparse.ArgumentParser()
parser.add_argument('--from', dest="fromd", type=str, required=True, help="From date")
parser.add_argument('--to', dest="tod", type=str, required=True, help="To date")
parser.add_argument('--range', dest='drange', action='store_true', help="Delete files between the given date")
parser.add_argument('--out-range', dest="orange", action='store_true', help="Delete files apart form the given date")

args = parser.parse_args()

if args.drange and args.orange:
    print('Enter either --range or --out-range option')
    sys.exit(1)
elif not (args.drange or args.orange):
    print('You must select either --range or --out-range option')
    sys.exit(1)

from_date = args.fromd
to_date = args.tod
path='/tmp/tmp.54JUy4ZP6x/'


try:
    from_date = datetime.datetime.strptime(from_date, '%Y%m%d').date()
    to_date   = datetime.datetime.strptime(to_date, '%Y%m%d').date()
except ValueError:
    print('Check if the date has been given in YYYYMMDD format')
    sys.exit(1)

files = [ x for x in os.listdir(path) if x.endswith('.txt') ]


for file in files:

    file_date = datetime.datetime.strptime(file[17:25], '%Y%m%d').date()

    if args.orange:
        # Delete files out of date range
        if not from_date < file_date < to_date:
            print('Deleting file {}'.format(file))
            os.remove(path + '/' + file)
    else:
        # Delete files within date range
        if from_date < file_date < to_date:
            print('Deleting file {}'.format(file))
            os.remove(path + '/' + file)

Aqui todos os parâmetros são configuráveis, exceto que o path precisa ser alterado no programa.

Espero que ajude você.

    
por 05.11.2014 / 14:33