如何使用Perl检查文件的扩展名?

如何使用Perl检查文件的扩展名?,perl,file,Perl,File,对于我的perl脚本,一个文件作为参数传递。该文件可以是.txt文件,也可以是包含.txt文件的.zip文件 我想写类似这样的代码 if ($file is a zip) { unzip $file $file =~ s/zip$/txt/; } 检查扩展的一种方法是对执行拆分,然后匹配数组中的最后一个结果(由拆分返回) 有更好的方法吗?检查文件名的结尾怎么样 if ($file =~ /\.zip$/i) { 然后: use strict; use Archive::Ex

对于我的perl脚本,一个文件作为参数传递。该文件可以是
.txt
文件,也可以是包含
.txt
文件的
.zip
文件

我想写类似这样的代码

if ($file is a zip) {

    unzip $file
    $file =~ s/zip$/txt/;
}
检查扩展的一种方法是对
执行拆分,然后匹配数组中的最后一个结果(由拆分返回)


有更好的方法吗?

检查文件名的结尾怎么样

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();
}

更多信息。

您可以使用正则表达式匹配项检查文件扩展名,如下所示:

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

为什么要依赖文件扩展名?只需尝试解压缩并使用适当的异常处理:

eval {
    # try to unzip the file
};

if ($@) {
    # not a zip file
}

另一个解决方案是利用它来确定二进制文件的类型

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
}

这样,您就不必处理丢失/错误的扩展名。

您可以使用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

我知道这个问题已经问了好几年了,但对于将来来到这里的任何人来说,将文件路径分解为其组成路径、文件名、基名称和扩展名的简单方法如下

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

希望这能有所帮助。

可能有点晚,但可以作为替代参考:

sub unzip_all {
     my $director = shift;
     opendir my $DIRH, "$director" or die;
     my @files = readdir $DIRH;
     foreach my $file (@files){
              my $type = `file $director/$file`; 
              if ($type =~ m/gzip compressed data/){
                      system "gunzip $director/$file";
              }
      }       
      close $DIRH;
      return;
}

这里可以使用linux通过使用(``)从perl执行它。您可以传递文件夹的路径,并评估是否存在按
file
分类为gzip压缩的文件

您确定只想检查分机吗?如果您希望测试正在处理的文件类型,最好检查mime类型。看看下面这样的例子:支持@totels和一些较低的回答。我很惊讶有多少人认为依赖扩展是安全的(
mv virus.exe hooters.jpg
)或健壮的(
mv some-mage-dossy-garbage.bin whatever.zip
)。假设zip和捕捉错误或探索MIME类型是正确的答案。任何使用扩展名的解决方案都是错误的。+1,但是您应该替换
my$file\u type=file::type->mime\u type($file)
my$file\u type=$ft->mime\u type($file)
File::Type
在这里工作,但与之相比,通常做的工作相当糟糕。这可能是最好的方法(无论是哪个模块),但是-T File测试操作符可能也值得一看。daxim:我将尝试
File::LibMagic
。谢谢。如果您的系统上没有安装“unzip”,或者它不在您的路径中,该怎么办?@Prakash:
unzip
应该是一个perl函数。没关系,替换为注释:)
fileparse
首先返回文件名,而不是目录。当然,你是对的,我已经修复了它。奇怪的是,五年多以来它都没有被注意到。谢谢你指出。不用担心,你的帖子在我整理好订单后解决了我的问题:)
sub unzip_all {
     my $director = shift;
     opendir my $DIRH, "$director" or die;
     my @files = readdir $DIRH;
     foreach my $file (@files){
              my $type = `file $director/$file`; 
              if ($type =~ m/gzip compressed data/){
                      system "gunzip $director/$file";
              }
      }       
      close $DIRH;
      return;
}