【问题标题】:Writing to a file inside if statement not working in Perl写入 if 语句中的文件在 Perl 中不起作用
【发布时间】:2026-01-03 00:45:01
【问题描述】:

我在这里环顾了一下,发现了类似的问题,但不完全是。如果有的话,我很抱歉,请指点一下。

我有以下代码。我正在尝试创建一个简单的从文件名和文件名本身提取的 ID 的 csv 文件。这是整个脚本。

use strict;
use warnings;
use File::Find;

find( \&findAllFiles, '.');
exit;

sub findAllFiles {

my @fp1;
my @fp2;
my $patId;
my $filename;
my $testvar = "hello again";


$filename = $File::Find::name;

if ($filename =~ /\.pdf$/) {
open (my $fh, '>', 'filenames.csv') or die "Failed to open - $!\n";
print $fh "starting...$testvar\n" or die "Failed to print to file - $!\n";
    @fp1 = split('/', $filename);
    @fp2 = split('_', $fp1[-1]);
    $patId = $fp2[-1];
    $patId =~ s/\.pdf$//;
    print "Adding $patId, file = $filename\n";
    print $fh "$patId,$filename\n" or die "File print error: $!";
close $fh or warn "close failed! - $!";
}


return;
}

打印到屏幕上的行打印完美。 如果我从if 块中取出文件打开/关闭和第一个打印语句,它将该行打印到文件中,而不是块内的数据。 我已经尝试了所有我能想到的组合,但它不起作用。我在'>''>>' 之间交替使用,因为它显然需要追加,因为它循环文件名,但在if 块内都不起作用。

即使上面的这段代码也不会抛出die 错误!它只是忽略了那些行!我想我缺少一些明显的东西。

【问题讨论】:

  • 我不确定我是否完全理解了您的问题(“它不起作用”不是一个很好的描述),但是 find( { wanted => \&findAllFiles, no_chdir => 1}, '.'); 而不是您的 find( \&findAllFiles, '.');(和>> 而不是 >) 解决了吗?
  • 你永远不会真正打印出$File::Find::name$filename 的值。所以我的第一个猜测是你的文件名与你的正则表达式不匹配。
  • 1) 实际上,我确实打印出 $filename 并且它完全正确地打印到屏幕上。 2)@Dada - 它奏效了!我不知道那个 sn-p 是什么意思,但它做到了!谢谢!
  • 请注意,filenames.csv 将在找到 pdf 的目录中创建,因为 find() 在搜索时会更改目录;这就是你想要的吗?
  • 是否显示“正在添加...”消息?

标签: perl if-statement file-writing


【解决方案1】:

引用File::Find::find的文档:

此外,对于找到的每个目录,它都会 chdir() 进入该目录

这意味着当您在findAllFiles 中使用open 时,您可能会在初始目录的子目录中打开文件filenames.csv。你可以从终端运行类似find . -name filenames.csv 的东西,你会看到很多filenames.csv。您可以通过将no_chdir 选项传递给find 来更改此行为:

find( { wanted => \&findAllFiles, no_chdir => 1}, '.');

(另外在您的公开场合将> 更改为>>

但是,就我个人而言,我会避免重复打开和关闭 filenames.csv,因为您可以在调用 find 之前打开它一次。如果您不想全局定义文件句柄,可以随时将其作为参数传递给findAllFiles

{ 
    open my $fh, '>', 'filenames.csv' or die "Failed to open 'filenames.csv': $!";
    find(sub { findAllFiles($fh) }, '.')
}

sub findAllFiles {
    my ($fh) = @_;
    ...

【讨论】:

    【解决方案2】:

    filenames.csv 将在找到 pdf 的目录中创建,因为 find() 在搜索时会更改目录。如果这不是您想要的,请使用绝对路径打开它(或在调用 find 之前打开它,这似乎是一个更好的主意)。

    【讨论】: