简体   繁体   English

通过目录树递归的Perl脚本

[英]Perl script that recurses through a directory tree

I want to write a Perl script that starts at the top of a directory tree (provided in the command line arguments) and recursively moves through each sub-directory, performing a certain action on each file. 我想编写一个Perl脚本,该脚本从目录树的顶部开始(在命令行参数中提供),然后递归地遍历每个子目录,并对每个文件执行特定操作。

I'm using finddepth for this, however it does not seem to work when I run the script on a directory that is two levels or more from the base directory. 我正在为此使用finddepth ,但是当我在距基本目录finddepth两个级别的目录上运行脚本时,它似乎不起作用。

Here is my code: 这是我的代码:

#!/usr/local/bin/perl -w

use strict;

use File::Copy;
use File::Find;
use File::Basename;
use File::Path;

finddepth(\&file_list, @ARGV);

sub file_list {

    my ($file_path, $name, $path, $suffix);

    $file_path = $File::Find::name;

    ($name, $path, $suffix) = fileparse($file_path, /\.*/);

    my $fullname = $name . $suffix;
    my $file = $fullname;

    if ($file =~ /^[^\.].*[^\.pl]$/) {

        copy($file, "$file.orig");

        open(FILE, "$file");
        my @file_data = <FILE>;
        close(FILE);

        open(FOUT, ">$file") or die " \n File cannot be opened !";

        foreach my $line (@file_data) {
            if ($line =~ /^\s+Error:/) {
                $line =~ s/([^-]\d+)/ \*\*/gc;
                print FOUT $line;
            }
            else {
                print FOUT $line;
            }
        }
        close(FOUT);
    }
}

The following warnings/errors are consistently thrown: 始终发出以下警告/错误:

  1. Read on closed filehandle 在关闭的文件句柄上阅读
  2. File cannot be opened ! 文件无法打开!

I can't seem to figure out why this is happening. 我似乎无法弄清楚为什么会这样。 I've tried to make my question as specific as possible. 我试图使我的问题尽可能具体。 Please let me know if you need any more information. 如果您需要更多信息,请告诉我。 Thank you. 谢谢。

You can't open the file because $file happens to be a directory at that point in time, so you'll need to add a check for that. 您无法打开文件,因为$file当时恰好是一个目录,因此您需要为此添加一个检查。

It's probably worth adding an or die statement when opening the file for reading. 打开文件进行读取时,可能值得添加or die语句。

Also note that File::Find sets $_ to the current file name, so the 5 lines you take to produce $file are actually unnecessary. 还要注意, File::Find$_设置$_当前文件名,因此实际上不需要用5行来生成$file

There are a few problems with your code. 您的代码有一些问题。

  • use warnings is preferable to the command-line -w use warnings优于命令行-w

  • Declare your variables at their first point of use, not in a block at the top of the the subroutine 在第一个使用点声明变量,而不是在子例程顶部的块中声明

  • Use the three-parameter form of open , and lexical file handles 使用open和lexical文件句柄的三参数形式

  • When checking the status of an open call, put the built-in variable $! 检查open呼叫的状态时,请放置内置变量$! in the die string so that you know why the open failed die的字符串,让你知道为什么打开失败

  • Don't put scalar variables inside double quotes. 不要将标量变量放在双引号中。 It is probably unnecessary and under some circumstances can break your code. 这可能是不必要的,在某些情况下可能会破坏您的代码。 It is highly unlikely to do anything you want 极不可能做任何你想做的事

This rewrite of your program uses use autodie to avoid the need for explicit open ... or die $! 程序的这种重写use autodie来避免显式open ... or die $! statements. 陈述。 It uses rename to change the name of the file instead of copying it and overwriting the original. 它使用rename来更改文件名,而不是复制文件并覆盖原始文件。

Instead of reading the entire file into memory, I open the renamed file and read it line by line, editing and writing each line to the new file 我没有将整个文件读入内存,而是打开重命名的文件并逐行读取,然后将每一行编辑并写入新文件

I have written it so that it ignores files that begin with a dot or end with .pl - I hope that's right. 我已经编写了它,以便它忽略以点开头或以.pl结尾的文件-我希望是正确的。 I am also very dubious about your substitution s/[^-]\\d+/ **/g which looks for a sequence of digits preceded by a character that isn't a hyphen; 对于您的替换s/[^-]\\d+/ **/g ,我也非常怀疑,该替换会查找以连字符开头的数字序列。 is that right? 那正确吗?

#!/usr/local/bin/perl

use strict;
use warnings;

use autodie;
no autodie 'unlink';

use File::Find 'finddepth';

finddepth(\&file_list, @ARGV);

sub file_list {

  return unless -f;
  return if /^\./ or /\.pl$/;

  my $file = $_;
  my $orig = "$file.orig";

  unlink $orig;
  rename $file, $orig;

  open my $infh, '<', $orig;
  open my $outfh, '>', $file;

  while (my $line = <$infh>) {
    if ($line =~ /^\s+Error:/) {
      $line =~ s/[^-]\d+/ **/g
    }
    print $outfh $line;
  }

  close $outfh;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM