2010-10-15 42 views
7

Để tập lệnh perl của tôi, một tệp được chuyển thành một cuộc tranh luận. Tệp có thể là tệp .txt hoặc tệp .zip chứa tệp .txt.Làm cách nào để kiểm tra phần mở rộng của một tệp bằng Perl?

Tôi muốn viết mã mà trông giống như sau

if ($file is a zip) { 

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

Một cách để kiểm tra phần mở rộng là để làm một sự chia rẽ trên . và sau đó kết hợp các kết quả cuối cùng trong mảng (được trả về bởi split).

Có cách nào tốt hơn không?

+8

Bạn có chắc chắn chỉ muốn kiểm tra tiện ích mở rộng không? Nếu bạn đang hy vọng kiểm tra loại tệp bạn đang xử lý, bạn nên kiểm tra loại mime. Hãy xem một cái gì đó như thế này: http://search.cpan.org/~pmison/File-Type-0.22/lib/File/Type.pm – totels

+0

Chim với hỗ trợ cho @totels và một vài câu trả lời đại diện thấp hơn . Tôi ngạc nhiên vì có bao nhiêu suy nghĩ dựa vào phần mở rộng hoặc là an toàn ('mv virus.exe hooters.jpg') hoặc mạnh mẽ (' mv some-huge-dossy-garbage.bin whatever.zip'). Giả sử lỗi zip và bắt hoặc khám phá kiểu MIME là các câu trả lời đúng. Bất kỳ giải pháp sử dụng phần mở rộng là một sai lầm. – Ashley

Trả lời

11

Bạn có thể sử dụng Tệp :: Tên cơ sở cho việc này.

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

Chạy điều này mang lại:

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

'fileparse' trả về tên tệp trước, không phải thư mục. –

+0

Bạn nói đúng, dĩ nhiên, và tôi đã sửa nó. Lạ lùng là nó không được chú ý trong hơn năm năm. Cảm ơn đã chỉ ra điều đó. –

+0

Đừng lo, bài đăng của bạn đã giải quyết được vấn đề của tôi khi tôi đã sắp xếp thứ tự :) –

6

Làm cách nào để kiểm tra phần cuối của tên tệp?

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

và sau đó:

use strict; 
use Archive::Extract; 

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

biết thêm thông tin here.

2

Bạn có thể kiểm tra phần mở rộng tập tin bằng một trận đấu regex như:

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

Tại sao dựa vào phần mở rộng tập tin? Chỉ cần cố giải nén và sử dụng xử lý ngoại lệ thích hợp:

eval { 
    # try to unzip the file 
}; 

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

Nếu bạn không cài đặt 'giải nén' trên hệ thống của mình, hoặc nếu nó không nằm trong đường dẫn của bạn thì sao? –

+0

@Prakash: 'giải nén' được cho là một hàm perl.Nevermind, thay thế bằng comments :) –

12

Một giải pháp khác là sử dụng loại tệp nhị phân.

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 
} 

Bằng cách này, bạn không phải xử lý các tiện ích bị thiếu/sai.

+1

+1, nhưng bạn nên thay thế 'my $ file_type = File :: Type-> mime_type ($ file);' bởi 'my $ file_type = $ ft-> mime_type ($ file);' – Toto

+0

Cảm ơn bạn đã chỉ ra điều đó. –

+2

'File :: Type' hoạt động ở đây, nhưng nói chung là một công việc khá crappy so với [' File :: LibMagic'] (http://p3rl.org/File::LibMagic). – daxim

1

Tôi biết câu hỏi này là một vài tuổi, nhưng đối với bất cứ ai mà đến đây trong tương lai, một cách dễ dàng để phá vỡ một đường dẫn tập tin vào con đường cấu thành của nó , tên tệp, tên cơ sở và đuôi mở rộng như sau.

use File::Basename; 

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

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

Bạn có thể kiểm tra kết quả bằng những điều sau đây.

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

Hy vọng điều này sẽ hữu ích.

Các vấn đề liên quan