【问题标题】:How do I run a Perl script on multiple input files with the same extension?如何在具有相同扩展名的多个输入文件上运行 Perl 脚本?
【发布时间】:2010-12-15 07:02:47
【问题描述】:

如何在具有相同扩展名的多个输入文件上运行 Perl 脚本?

 perl scriptname.pl file.aspx

我希望为当前目录中的所有 aspx 文件运行它

谢谢!

【问题讨论】:

标签: perl command-line


【解决方案1】:

在您的 Perl 文件中,

 my @files = <*.aspx>;
 for $file (@files) {

      # do something.

 }

&lt;*.aspx&gt; 称为glob

【讨论】:

  • 这行得通,但只有当您没有为您完成这项工作的 shell 时才需要(或者脚本可能通过 GUI 启动器启动) - 甚至不是那么灵活虽然它完成了工作。
  • 感谢您的评论。但是重读这个问题,我认为这个答案不需要限定。此外,我更愿意在程序本身内部使用“获取所有扩展名为 .aspx 的文件”逻辑,而不是使用命令行。
  • @Jonathan:OP 很可能在 Windows 上运行,使用 cmd shell。据我所知,cmd 不像 Unix shell 那样进行通配符扩展。
  • @Jonathan:如果文件数量太大,也会有问题。
  • 您无需告诉人们 是一个 glob,您只需在开始时使用 glob('*.aspx')。 :)
【解决方案2】:

您可以使用通配符将这些文件传递给 perl

在你的脚本中

foreach (@ARGV){
    print "file: $_\n";
    # open your file here...
       #..do something
    # close your file
}

在命令行上

$ perl myscript.pl *.aspx

【讨论】:

  • 在 Windows 上 @ARGV 将只有一项:“*.aspx”。
【解决方案3】:

您可以显式使用glob 来使用shell 参数,而无需过多依赖shell 行为。

for my $file ( map {glob($_)} @ARGV ) { 
   print $file, "\n";
};

您可能需要通过扩展多个参数来控制文件名重复的可能性。

【讨论】:

    【解决方案4】:

    对于带有-n-p 的简单单行,您需要

    perl -i~ -pe 's/foo/bar/' *.aspx
    

    -i~ 表示修改每个目标文件,并将原始文件保留为备份,并在文件名中添加~ 后缀。 (省略后缀以不留下备份。但是,如果您仍在学习或试验,这是一个坏主意;完成后删除备份比如果您搞砸了从备份中恢复原件麻烦得多。 )

    如果你的 Perl 代码对于单行代码来说太复杂(或者只是有用到可以重用),显然用 scriptname.pl 替换 -e '# your code here' ...尽管然后可能重构 scriptname.pl 以便它接受一个列表文件名参数,只需使用scriptname.pl *.aspx 在当前目录中的所有*.aspx 文件上运行它。

    如果您需要递归目录结构并查找具有特定命名模式的所有文件,find 实用程序很有用。

    find . -name '*.aspx' -exec perl -pi~ -e 's/foo/bar/' {} +
    

    如果您的find 不支持-exec ... +,请尝试使用-exec ... \;,尽管它会更慢并启动更多进程(您找到的每个文件一个,而不是尽可能少地处理所有文件)。

    要仅扫描某些目录,请将.(命名当前目录)替换为以空格分隔的要检查的目录列表,甚至使用find 查找目录本身(然后也许探索@987654339 @ 用于在 find 选择的每个目录中使用您的复杂、错综复杂、业务关键、可能是 find 选项谓词的秘密列表进行操作)。

    也许还可以探索 find2perl 在 Perl 中本地执行此目录递归。

    【讨论】:

      【解决方案5】:

      如果你在 Linux 机器上,你可以试试这样的。

      for i in `ls /tmp/*.aspx`; do perl scriptname.pl $i; done
      

      【讨论】:

      • 无用的ls。 -- for i in /tmp/*
      • 其实应该是./*.aspx来回答问题。
      • 我发现使用 ls 对于您希望按特定顺序处理文件的情况非常有用。例如,ls -tr ./*.aspx 将按照修改顺序对所有文件运行 perl 脚本。
      • 当然,如果 scriptname.pl 被写入处理输入文件名列表,那么简单的 perl scriptname.pl *.aspx 应该可以工作。
      • @Ari 保留修改顺序的用例到底是什么?如果 Perl 脚本在合理的时间内执行,无论如何文件都将在同一秒内被修改,或者如果脚本有点慢或有很多文件(或者如果脚本真的很慢,则不相邻,但是那么,如果这是一项重要的工作,您是否有足够的勇气自动运行它?)如果您确实需要,没有various well-documented perils of ls 的一个很好的解决方法是使用带有合适选项的find
      【解决方案6】:

      例如处理perl scriptname.pl *.aspx *.asp

      在linux中:shell扩展通配符,所以perl可以简单

      for (@ARGV) {
        operation($_); # do something with each file
      }
      

      Windows 不扩展通配符,因此在 perl 中扩展每个参数中的通配符,如下所示。然后 for 循环以与上述相同的方式处理每个文件

      for (map {glob} @ARGV) {
        operation($_); # do something with each file
      }
      

      例如,这将在 Windows 下打印展开的列表

      print "$_\n" for(map {glob} @ARGV);
      

      【讨论】:

        【解决方案7】:

        您还可以传递您拥有 aspx 文件的路径并一一读取。

        #!/usr/bin/perl -w
        
        use strict;
        
        my $path = shift;
        my @files = split/\n/, `ls *.aspx`;
        
        foreach my $file (@files) {
                do something...
        }
        

        【讨论】:

        • 您不需要使用 ls,这在某些系统上甚至可能不是有效的命令。
        • 即使在ls 可用的系统上,在这里使用它也是错误的工具,并且有multiple well-documented issues。 Perl 内置了通配符,所以很简单 foreach my $file (&lt;*.aspx&gt;) 或者如果您的需求有点复杂,作为代码的骨架,opendir 目录和循环文件,在循环内部的顶部执行 next unless /\.aspx$/
        猜你喜欢
        • 2017-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多