Newsgroup: it.comp.lang.perl
Titolo: dividere nomefile

Ciao a tutti,
premetto che non agli inizi con perl e ho la seguente necessità:
Voglio leggere tutti i file in una cartella per poter cancellare quelli 
vecchi.
I file sono nominati in questa maniera : aaaammgg-hh
Ora.. avendo per esempio il file 20071219-14, come posso 'splittare' il 
nome file in più parti assegnando i primi 4 caratteri alla variabile 
$anno, il 5° e il 6° alla variabile $mese, il 7° e l'8° alla variabile 
$giorno e troncare i rimanenti (in modo da poter poi controllare se la 
directory deve essere cancellata o meno, e nel caso rimuoverla) ?
Grazie mille!
YUS

YUS ha scritto:

Pardon, una imprecisione.. sto parlando di directory.. non di file.
aaaammgg-hh è il nome della directory che contiene a sua volta dei 
file.. una volta stabilito se la directory è sufficientemente vecchia 
procedo alla cancellazione.
YUS

 YUS
opendir DIR, ".";
@subdir = readdir DIR;
e nell' array @subdir hai tutti i nomi di directory contenute
nella dir attuale ".".
ora, fisto che i nomi sono cosi' ben formalizzati, hai diversi approcci:
1) il piu' furbo!! Se ci fai caso il formato AAAAMMGG (che anche io
   preferisco SEMPRE) HA CARATTERISTICHE ORDINALI SIA COME NUMERO CHE COME
   STRINGA!! Quindi se hai un timestamp di 32 bits come soglia di
   "vecchiaia" puoi convertire anche lui in formato AAAAMMGG e usare
   gli operatori di confronto stringa (lt, le, gt, le)
   Per convertire un timestamp usi localtime o gmtime a piacere.
   quindi se decidi che tutte le dir pu' vecchie e quindi ordinalmente
   minori di "20070901" ti basta un ciclo simile a questo:
   for my $temp (@subdir) { if ($temp le "20070901") { purgadir($temp)} }
     # per realizzare purgadir userai appropriatamente unlink e rmdir
2) Vuoi proprio sapere come splittare la stringa AAAAMMGG nei campi
   AAAA MM GG per poi convertirli in int, ottenere un timestamp e
   usare quello per i confronti, a quel punto con gli operatori per interi
   (< <= > >=) e per fare questo ci sono almeno 2 modi:
   2.1) metodo perlista maniaco di RE:
        $nomedir = "20070502-11";
        $nomedir =~ /(dddd)(dd)(dd)-(dd).*/g;
        print "-$1-$2-$3----$4n";
        nelle var $1 $2 $3 $4 hai i 4 campi numerici.
   2.2) metodo vecchio programmatore C tirchio di cicli macchina:
        $anno = substr $nomedir, 0, 4;
        $mese = substr $nomedir, 4, 2;
        $giorno = substr $nomedir, 6, 2;
        $progressivo = substr $nomedir, 9, 2;
   in Perl gli scalari che contengono stringe "2007" sono immediatamente
   usabili come interi, cioe' inserite in espressioni con operatori per
   interi.
Ciao
Roberto.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

         nelle var $1 $2 $3 $4 hai i 4 campi numerici.
Preferisco:
   if (my ($anno, $mese, $giorno, $progressivo) =
         $nomedir =~ /\A (\d{4}) (\d\d) (\d\d) - (\d\d) \z/mxs) {
      # controlla & purga...
   }
Questo consente di avere i risultati già direttamente dove voluto, e
di controllare al contempo che $nomedir si adatti al formato
stabilito.
Per le stringhe a formato predefinito (per le quali sei *sicuro* del
formato) puoi usare anche unpack:
   my ($anno, $mese, $giorno, $progressivo) = unpack 'A4 A2 A2 x A2',
$nomedir;

 $nomedir;
Non avevo pensato a unpack(); Quindi e' questo il metodo piu' veloce.
Grazie e ciao.


> Non avevo pensato a unpack(); Quindi e' questo il metodo piu' veloce.
No, caro tirchione di cicli macchina, il tuo sistema è più veloce. Ho
fatto un rapido benchmarking, e la soluzione con le substr è ancora la
più rapida. Per la strada ho anche scoperto che queste funzioni
sembrano diventate più lente in perl 5.10.0 (v. 
http://www.perlmonks.org/?node_id=658738
):