Thread code erweitern (10 answers)
Opened by nethawk at 2010-03-12 14:22

topeg
 2010-03-15 11:37
#134852 #134852
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Dazu bedarf es größerer Umbauarbeiten am Script:
Ich nutze File::Find um die Verzeichnisse zu lesen, File::Spec um die Verzeichnisse/dateien vernünftig zu handhaben und File::stat um das "stat" lesbarer zu machen.
Von File::Copy nutze ich "move" um die zu löschende Datei zu verschieben
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!c:/perl/bin/perl -w
# das sind module für strictes programmieren und warnungen
use strict;
use warnings;
use File::Copy;
use File::Spec;
use File::Find;
use File::stat;

# ein paar konstanten

use constant LOESCHEN => 0;
use constant BEHALTEN => 1;
use constant DELETED => -1;
use constant MOVED => 2;

# dein ordner wo drinne geloescht werden soll

my $srcDir = 'C:\test';
my $destDir = 'C:\backup';
my $oldInDays=30;

# das log file

my $logFile = File::Spec->join($srcDir,'log.txt');

# zeitpunkt minus $oldInDays tage also alt die dateien und ordner hoechstens sein dürfen
my $backxdays = (time()-(86400*$oldInDays));

# hier springt er in die sub read_dirs
# und liefert einen Hash mit relativen Pfadangaben zurück
my %allFiles=read_dirs(File::Spec->rel2abs($srcDir));

# alle dateien durchgehen und schauen ob sie aelter als 30 tage sind
# ordner werden automatisch auf loeschen gesetzt

for ( sort keys(%allFiles))
{
  # aus dem relaitven Pfad einen absoluten machen
  my $srcName=File::Spec->rel2abs($_, $srcDir);
  # ModifikationsZeit lesen
  my $lastMod = stat($srcName)->mtime();

  # ist es älter als erlaubt?
  $allFiles{$_} = BEHALTEN if(($lastMod - $backxdays) > 0 && -f $srcName);
  $allFiles{$_} = LOESCHEN if(($lastMod - $backxdays) < 0 && -f $srcName);
  $allFiles{$_} = LOESCHEN if -d $srcName;
}

# die dateien loeschen die aelter als 30 tage sind

for (sort keys(%allFiles))
{
  # für die Quelle aus dem relaiven einen absoluten Pfad machen
  my $srcName=File::Spec->rel2abs($_, $srcDir);
  # ist es eine Datei und soll gelöscht werden?
  if ($allFiles{$_} == LOESCHEN && -f $srcName)
  {
    # für das Ziel aus dem relaiven einen absoluten Pfad machen
    my $destName=File::Spec->rel2abs($_, $destDir);

    # nötige Verzeichnisse am Ziel erstellen wenn es nötig ist.
    my ($volume,$directories,$file) = File::Spec->splitpath( $destName );
    make_dirs(File::Spec->catpath($volume, $directories));

    # Datei verschieben
    $allFiles{$_} = MOVED if move($srcName,$destName);
  }
}

# die ordner loeschen die leer sind
# rmdir loescht nur leere ordner

foreach( sort keys(%allFiles))
{
  if ($allFiles{$_} == LOESCHEN && -d $_)
  {
    my $DirName=File::Spec->rel2abs($_, $srcDir);
    $allFiles{$_} = DELETED if rmdir($DirName);
  }
}

# den ganzen spass in ne log datei schreiben
&loggen($logFile,$srcDir,%allFiles);

########################################################################
########################################################################
# logdatei schreiben
sub loggen
{
  my $logfile=shift;
  my $srcdir=shift;
  my %files=@_;
  open(my $logfh, '>', $logfile) or die "ERROR open: $logfile ($!)";

  foreach(sort keys(%files))
  {
    my $filename=File::Spec->rel2abs($_, $srcdir);
    print $logfh $filename," --> ";
    print $logfh "File/Directory wurde geloescht...\n\n" if $files{$_} == DELETED;
    print $logfh "File/Directory ist aktuell...\n\n" if $files{$_} == BEHALTEN;
    print $logfh "File/Directory wurde nicht geloescht...\n\n" if $files{$_} == LOESCHEN;
    print $logfh "File/Directory wurde verschoben...\n\n" if $files{$_} == MOVED;
  }
  close($logfh);
}

# Diese Funktion nutzt File::Find um alle Unterverzeichnisse nach Dateien zu durchsuchen
# und liefert einen Hash zurück der alle Dateien und Ordner als relaitiven pfad zu "$dir" enthält

sub read_dirs
{
  my $dir = shift;
  my %files=();
  # File::Find::find ausführen
  find(sub{
    # nicht eigener Ordner und vorheriger
    return if($_ eq '.' || $_ eq '..');
    # Pfadanagen von Absolut nach relative wandeln
    my $name=File::Spec->abs2rel($File::Find::name,$dir);
    # Haswert setzen
    $files{$name}=undef;
  }, $dir);
  return %files;
}

# Erzeugen von Verzeichnissen wenn sie nicht existieren

sub make_dirs
{
  my $path=shift;

  my $dnow='';
  ($dnow,$path)=File::Spec->splitpath($path, 1);
  for(File::Spec->splitdir($path))
  {
    $dnow=File::Spec->join($dnow, $_);
    unless(-d $dnow)
    { mkdir($dnow) or die("ERROR mkdir: $dnow ($!)"); }
  }
}


Das ist nicht getestet, sollte aber ausführbar sein.
EDIT:
kleiner Fehler in Zeile 47 "$srcName" statt $_;
Last edited: 2010-04-15 18:41:30 +0200 (CEST)

View full thread code erweitern