Répertorier / supprimer des fichiers, avec des noms de fichiers contenant une chaîne datant de «plus d'un mois»?

0

Je stocke des données dans des fichiers qui suivent cette convention de nommage:

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

Comment chercher ceux avec date in file name < now - 1 month et les supprimer?

Les fichiers peuvent avoir changé depuis leur création. Vous devez donc effectuer une recherche en fonction de last modification date n'est pas bon.

Ce que je fais maintenant, c'est filtre en les 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))

Y a-t-il un (une doublure) bash solution pour cela?

Martin Tóth
la source

Réponses:

1

Peux tu utiliser -ctime avec find? Pour un fichier, ctime indique la dernière fois que les métadonnées du fichier ont été modifiées (création, renommage, chmod, chown, chgrp, etc.). Pour la plupart des fichiers journaux, la date de création et l'heure ctime seraient les mêmes.

Rich Homolka
la source
Selon man find: -ctime n Le statut du fichier a été modifié pour la dernière fois il y a n * 24 heures. Cela ne renvoie que les noms de fichiers de cette date exacte, mais dans mon cas, il peut y avoir des fichiers plus anciens que, et je ne peux pas dire quel âge ils ont, alors j'ai vraiment besoin d'un `& lt; `ou` & lt; = `comparaison.
Martin Tóth
Tu as raison. man find dit: Les arguments numériques peuvent être spécifiés comme suit: +n (pour plus que n), -n (pour moins que n), n (pour exactement n). Et cela fonctionne comme souhaité. Merci!
Martin Tóth
1

En présumant que la date GNU et GNU trouveront, vous pouvez le faire de cette façon

#!/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"

Mais ce n'est pas exactement un oneliner.

Comme cela est sous test et quelque peu dangereux, j’ai inclus un echo préfixe au rm commande, vous devrez donc la supprimer une fois que vous aurez vérifié que les résultats sont corrects.

Une faiblesse ici réside dans la sélection initiale des fichiers. -path "$prefix"'*' suppose des chemins absolus et va casser autrement; une sélection plus intelligente est probablement meilleure, même s’il s’agit d’un simple shell glob (c'est-à-dire, remplacer la boucle while par for file in "$prefix*" ; do ... done. Je ne l'ai pas fait parce que je ne sais pas si une telle expansion globale déborderait la longueur de commande maximale.

phogg
la source
1
Intéressant, il fait le compare. Ce sera un peu plus lent à cause de tous les touch des dossiers. le find . ! -newer' can much more simply be replaced by the [$ FILE1 -ot $ FILE2] `, au moins en bash.
Rich Homolka
Étant donné tous les GNUismes présents, y compris l'invocation explicite de bash et l'utilisation de la syntaxe de recherche non portable, je ne pense pas que quiconque puisse s'opposer à l'utilisation de -ot. J'aurais utilisé cette comparaison si j'y avais pensé, mais au lieu de cela, j'ai recyclé une solution que j'avais utilisée auparavant (lorsque j'avais GNU find sous Windows, mais aucun sh).
phogg
Comme il s'avère que vous pouvez utiliser -newerXYY est t spécifier directement un horodatage (pour GNU find c'est GNU date -d format) pour éviter de créer un fichier intermédiaire. Ce sera un peu plus rapide, comme le mentionne Rich.
phogg