Listar / remover arquivos, com nomes de arquivos contendo uma string que é “mais de um mês atrás”?

0

Eu armazeno alguns dados em arquivos que seguem esta convenção de nomenclatura:

/interesting/data/filename-YYYY-MM-DD-HH-MM

Como procuro os com date in file name < now - 1 month e os excluo?

Os arquivos podem ter sido alterados desde que foram criados, portanto, pesquisar de acordo com last modification date não é bom.

O que eu estou fazendo agora é filtrar - inserindo-os em python:

prefix = '/interesting/data/filename-'

import commands
names = commands.getoutput('ls {0}*'.format(prefix)).splitlines()

from datetime import datetime, timedelta

all_files = map(lambda name: {
    'name': name,
    'date': datetime.strptime(name, '{0}%Y-%m-%d-%H-%M'.format(prefix))
}, names)

month = datetime.now() - timedelta(days = 30)
to_delete = filter(lambda item: item['date'] < month, all_files)

import os
from operator import itemgetter
map(os.remove, map(itemgetter('name'), to_delete))

Existe uma solução (oneliner) bash para isso?

    
por Martin Tóth 12.01.2011 / 17:54

2 respostas

1

Você pode usar -ctime com find ? Para um arquivo, ctime indica a última vez que os metadados do arquivo foram alterados (criação de arquivo, renomeação, chmod, chown, chgrp, etc). Para a maioria dos arquivos de log, a data de criação e a hora seria a mesma.

    
por 12.01.2011 / 22:43
1

Presumindo a data GNU e o GNU, você pode fazer desta maneira

#!/usr/bin/env bash

prefix="/interesting/data/filename-"
ref=/tmp/ref.$$
one_month_ago=/tmp/one_month_ago.$$
results=/tmp/results.$$

# create a file whose timestamp is "one month ago"
touch "$one_month_ago" -t $(date -d "-1 month" +%Y%m%d%I%M.%S)

while read -r file ; do
        # strip the prefix, leaving the suffix
        datestr=$(tail -c $(( ${#file} - ${#prefix} + 1 )) <<<"$file")

        # cut the date and time out of the suffix
        date=$(cut -d- -f1-3 <<<"$datestr")
        time=$(cut -d- -f 4- <<<"$datestr" | tr - :)

        # create a reference file whose timestamp matches the string from $file
        touch "$ref" -t $(date -d "$date $time" +%Y%m%d%I%M.%S)

        # ask find whether the reference file is not neewer (aka "is older") 
        # than one month ago
        find "$ref" -not -newer "$one_month_ago" > "$results" &&
                # results from find?
                [ -s "$results" ] &&
                # then rm the corresponding file
                echo rm -f -- "$file"

done < <(find -path "$prefix"'*')

# clean up
rm -f "$ref" "$one_month_ago" "$results"

Mas não é exatamente um oneliner.

Como isso está sendo testado e um pouco perigoso, incluí um prefixo echo no comando rm , então você precisará removê-lo assim que verificar que os resultados estão corretos.

Uma fraqueza aqui está na seleção inicial de arquivos. -path "$prefix"'*' presume caminhos absolutos e irá quebrar de outra forma; uma seleção mais inteligente é provavelmente melhor, mesmo se for um simples shell glob (ou seja, substituir o loop while por for file in "$prefix*" ; do ... done . Eu não fiz isso porque não sei se essa expansão glob iria ou não transbordar o máximo comprimento do comando.

    
por 13.01.2011 / 19:33

Tags