2010-10-15 13 views
7

Al mio script perl, un file viene passato come argomento. Il file può essere un file .txt o un file .zip contenente il file .txt.Come posso controllare l'estensione di un file usando Perl?

voglio scrivere codice che assomigli a questo

if ($file is a zip) { 

    unzip $file 
    $file =~ s/zip$/txt/; 
} 

Un modo per controllare l'estensione è quello di fare una spaccatura sulla . e quindi abbinare l'ultimo risultato nella matrice (restituito da split).

C'è un modo migliore?

+8

Sei sicuro di voler solo controllare l'estensione? Se speri di testare che tipo di file hai a che fare con te, sarebbe meglio controllare il tipo mime. Dai un'occhiata a qualcosa di simile a questo: http://search.cpan.org/~pmison/File-Type-0.22/lib/File/Type.pm – totels

+0

Chiming con supporto per @totels e un paio delle risposte inferiori . Sono sorpreso da quanti pensano che affidarsi all'estensione sia sicuro ('mv virus.exe hooters.jpg') o robusto (' mv some-huge-dossy-garbage.bin whatever.zip'). Supponendo zip e errori di cattura o esplorando il tipo MIME sono le risposte giuste date. Qualsiasi soluzione che utilizza l'estensione è un errore. – Ashley

risposta

11

È possibile utilizzare File :: Basename per questo.

#!/usr/bin/perl 

use 5.010; 
use strict; 
use warnings; 

use File::Basename; 

my @exts = qw(.txt .zip); 

while (my $file = <DATA>) { 
    chomp $file; 
    my ($name, $dir, $ext) = fileparse($file, @exts); 

    given ($ext) { 
    when ('.txt') { 
     say "$file is a text file"; 
    } 
    when ('.zip') { 
     say "$file is a zip file"; 
    } 
    default { 
     say "$file is an unknown file type"; 
    } 
    } 
} 

__DATA__ 
file.txt 
file.zip 
file.pl 

L'esecuzione di questo dà:

$ ./files 
file.txt is a text file 
file.zip is a zip file 
file.pl is an unknown file type 
+0

'fileparse' restituisce prima il nome del file, non la directory. –

+0

Hai ragione, ovviamente, e l'ho risolto. Strano che sia passato inosservato per oltre cinque anni. Grazie per segnalarlo. –

+0

Nessun problema, il tuo post ha risolto il mio problema una volta risolto l'ordine :) –

6

Come controllare la fine del nome file?

if ($file =~ /\.zip$/i) { 

e poi:

use strict; 
use Archive::Extract; 

if ($file =~ /\.zip$/i) { 
    my $ae = Archive::Extract->new(archive => $file); 
    my $ok = $ae->extract(); 
    my $files = $ae->files(); 
} 

ulteriori informazioni here.

2

È possibile controllare l'estensione del file utilizzando un match regex come:

if($file =~ /\.zip$/i) { 
     # $file is a zip file 
} 
2

Perché si basano su estensione del file? Basta provare a decomprimere e utilizzare la gestione delle eccezioni appropriata:

eval { 
    # try to unzip the file 
}; 

if ([email protected]) { 
    # not a zip file 
} 
+0

Cosa succede se non hai 'decomprimere' installato sul tuo sistema, o se non è nel tuo percorso? –

+0

@Prakash: 'unzip' dovrebbe essere una funzione perl.Nevermind, sostituito con commenti :) –

12

Un'altra soluzione è quella di fare uso di File::Type che determina il tipo di file binario.

use strict; 
use warnings; 

use File::Type; 

my $file  = '/path/to/file.ext'; 
my $ft  = File::Type->new(); 
my $file_type = $ft->mime_type($file); 

if ($file_type eq 'application/octet-stream') { 
    # possibly a text file 
} 
elsif ($file_type eq 'application/zip') { 
    # file is a zip archive 
} 

In questo modo, non è necessario gestire estensioni mancanti/errate.

+1

+1, ma dovresti sostituire 'my $ file_type = File :: Tipo-> mime_type ($ file);' per 'my $ file_type = $ ft-> mime_type ($ file);' – Toto

+0

Grazie per averlo indicato. –

+2

'File :: Type' funziona qui, ma in generale fa un lavoro piuttosto scadente rispetto a [' File :: LibMagic'] (http://p3rl.org/File::LibMagic). – daxim

1

So che questa domanda è di diversi anni, ma per chiunque che viene qui in futuro, un modo semplice per spezzare un percorso di file nel suo percorso costituente , nomefile, basename e l'estensione è la seguente.

use File::Basename; 

my $filepath = '/foo/bar.txt'; 

my ($basename, $parentdir, $extension) = fileparse($filepath, qr/\.[^.]*$/); 
my $filename = $basename . $extension; 

È possibile verificare i risultati con il seguente.

my @test_paths = (
    '/foo/bar/fish.wibble', 
    '/foo/bar/fish.', 
    '/foo/bar/fish.asdf.d', 
    '/foo/bar/fish.wibble.', 
    '/fish.wibble', 
    'fish.wibble', 
); 

foreach my $this_path (@test_paths) { 
    print "Current path: $this_path\n"; 
    my ($this_basename, $parentdir, $extension) = fileparse($this_path, qr/\.[^.]*$/); 
    my $this_filename = $this_basename . $extension; 

    foreach my $var (qw/$parentdir $this_filename $this_basename $extension/) { 
     print "$var = '" . eval($var) . "'\n"; 
    } 

    print "\n\n"; 
} 

Spero che questo aiuti.

Problemi correlati