2010-10-15 28 views
7

對我的perl腳本來說,文件是作爲一個參數傳遞的。該文件可以是.txt文件或.zip文件,其中包含.txt文件。如何使用Perl檢查文件的擴展名?

我想編寫代碼,看起來像這樣

if ($file is a zip) { 

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

一個檢查擴展的辦法是做.分裂,然後最後的結果數組(由split返回)的匹配。

有沒有更好的方法?

+8

您確定只想檢查擴展名嗎?如果你希望測試你正在處理的文件類型,那麼檢查MIME類型會更好。看看這樣的東西:http://search.cpan.org/~pmison/File-Type-0.22/lib/File/Type.pm – totels 2010-10-15 08:30:17

+0

支持@totels和一些較低的代表答案。我很驚訝有多少人認爲依靠這個擴展是安全的('mv virus.exe hooters.jpg')或強大的('mv some-huge-dossy-garbage.bin whatever.zip')。假設zip和捕獲錯誤或探索MIME類型是給出的正確答案。任何使用擴展的解決方案都是錯誤的。 – Ashley 2017-08-09 19:48:00

回答

11

您可以使用File :: Basename進行此操作。

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

運行這給:

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

'fileparse'首先返回文件名,而不是目錄。 – 2016-03-15 15:05:03

+0

當然你是對的,我已經修好了。奇怪的是,它被忽視了超過五年。感謝您指出。 – 2016-03-15 15:07:54

+0

不用擔心,一旦我整理了訂單,你的帖子就解決了我的問題:) – 2016-03-15 18:11:45

6

如何檢查文件名的結尾?

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

然後:

use strict; 
use Archive::Extract; 

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

更多信息here

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

可以使用正則表達式匹配作爲檢查的文件擴展名?只是嘗試解壓縮和使用適當的異常處理:

eval { 
    # try to unzip the file 
}; 

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

爲什麼依靠文件擴展名:

+0

如果您的系統上沒有安裝「解壓縮」,或者它不在您的路徑中,該怎麼辦? – 2010-10-15 13:03:10

+0

@Prakash:'unzip'應該是一個perl函數。沒關係,用註釋取代:) – 2010-10-15 13:16:58

12

另一個解決方案是利用File::Type這就決定二進制文件的類型。

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 
} 

這樣,您不必處理丟失/錯誤的擴展名。

+1

+1,但是你應該用'my $ file_type = $ ft-> mime_type($ file)來替換'my $ file_type = File :: Type-> mime_type($ file);''' – Toto 2010-10-15 08:45:21

+0

謝謝你指出。 – 2010-10-15 09:09:22

+2

'File :: Type'在這裏可以工作,但是與['File :: LibMagic'](http://p3rl.org/File::LibMagic)相比,通常做的工作相當糟糕。 – daxim 2010-10-15 10:36:09

1

我知道這個問題是幾年前的,但到這裏來的,今後任何人,一個簡單的方法來掰開文件路徑爲它的組成路徑,文件名,基本名稱和擴展名如下。

use File::Basename; 

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

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

您可以使用以下測試結果。

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"; 
} 

希望這會有所幫助。