Как найти старые большие файлы и сгенерировать метрики для каталогов, связывающихся с этими файлами - PullRequest
0 голосов
/ 02 января 2019

Я инженер по аппаратному обеспечению, работающий в отделе проектирования, и мы регулярно создаем каталоги с большими объемами данных (как большие файлы, так и каталоги, которые содержат большое количество маленьких файлов).Эти данные могут долго зависать на диске, и я ищу метрику, которая идентифицирует каталоги с большими объемами старых данных в качестве кандидатов на удаление.

Метрика, которую я выбрал, - это Размер файла(в M) * Возраст файла (в днях).

У меня есть рабочее решение, но оно представляет собой комбинацию сценариев оболочки и c и не является ни обслуживаемым, ни красивым, ни элегантным.

IЯ ищу идеи для улучшения сценария.

Основная идея состоит в том, чтобы сгенерировать необработанные данные по всем файлам, используя find

find $Dir -type f -exec stat -c "%s,%Y,%n" {} \; > rpt3

, а затем обработать этот файл в C, чтобы получить файл (rpt3b) в формате

Метрика, Возраст, Размер, Имя файла

Метрика - Возраст * Размер

Возраст - это количество дней с момента изменения файла

Размер - это размер файла в M

FileName - это имя файла.

Затем я обрабатываю этот файл для суммирования метрик для каждого каталога

for Directory in $( find /projects/solaris/implementation -maxdepth 4 -type d ) ; do
  Total=`grep $Directory/ rpt3a | sed -e 's?,.*??' | paste -sd+ - | bc`
  echo $Total,$Directory >> rpt3c
done

Таким образом, выводпохож на ду, но это показатель, который сообщается, а неразмер, взятый на диске.

Я мог бы сделать последний шаг в программе на C, но я ищу решение, которое идеально работает в одной среде (необязательно C, я открыт для изученияновые языки).

Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 02 января 2019

Звоните 'python script.py startdir ~/somefile.txt'.

Вы можете использовать это как начальную точку:

import os
import sys
import time

def get_age_in_days(file_stats):
    """Calculate age in days from files stat."""
    return (time.time() - file_stats.st_mtime) // (60*60*24) 

def get_size_in_MB(file_stats):
    """Calculate file size in megabytes from files stat."""
    return file_stats.st_size / (1024 * 1024)

def metric(root,f):
    """Uses root and f to create a metric for the file at 'os.path.join(root,f)'"""
    fn = os.path.join(root,f)
    fn_stat = os.stat(fn) 
    age = get_age_in_days(fn_stat)
    size = get_size_in_MB(fn_stat)
    metric = age*size

    return [metric, age, size, fn] 

path = None
fn   = None
if len(sys.argv)==3:
    path = sys.argv[1]
    fn = sys.argv[2]
else:
    sys.exit(2)


with open(fn,"w") as output:  
    # walk directory recursivly and report anything with a metric > 1 
    for root,dirs,files in os.walk(path):
        total_dict = 0
        for f in files:
            m = metric(root,f)

            # cutoff - only write to file if metric > 1
            if m[0] > 1: 
                total_dict += m[0]
                output.write(','.join(map(str,m))+"\n")
       output.write(','.join([str(total_dict), "total","dictionary",root])+"\n")

# testing purposes
# print(open(fn).read())

Файл примера - (без отсечки - используя https://pyfiddle.io/):

0.0,0.0,0.0011606216430664062,./main.py
0.0,0.0,0.0,./myfiles.txt
0.0,total,dictionary,./

Вы можете посмотреть любую строкусодержит ,total,dictionary,: 0.0,total,dictionary,./ для итоговых значений словаря.

0 голосов
/ 02 января 2019

Вы можете сделать все это в Perl. Perl поставляется с двумя операторами -M и -s, которые представляют собой соответственно возраст файла в днях и размер файла в байтах. Age - время запуска скрипта минус время модификации файла, а также модуль File::Find, который имитирует команду find.

#!perl
use strict;
use warnings;

use File::Find;

find(\&process, shift); # shift the start directory off @ARGV

sub process {
    # Lots of use of the magic _ file handle so we don't keep having to call stat()
    print( (-M _) * (-s _), ' ', -M _, ' ', -s _, " $File::Find::name\n")
        if -f $_;
}
0 голосов
/ 02 января 2019

Используйте cut, чтобы извлечь правильный столбец из извлеченных строк вместо sed.cut -d, -f3 извлечет третий столбец, каждый из которых разделен ,.

С помощью ввода:

10,2,5,a/b
20,4,5,a/c
30,2,15,b/d
40,4,10,a/d

команда grep a/ a.txt | cut -f3 -d, | paste -sd+ - | bc выдаст:

20

икоманда grep b/ a.txt | cut -f3 -d, | paste -sd+ - | bc:

15
...