写入 if 语句中的文件在 Perl 中不起作用
Writing to a file inside if statement not working in Perl
我在这里四处看了看,发现了类似的问题,但不完全是。如果有的话,我很抱歉,请指点一下。
我有以下代码。我正在尝试创建一个仅包含从文件名和文件名本身提取的 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
块中取出文件 open/close 和第一个打印语句,它会将那行打印到文件中,而不是块内的数据。
我已经尝试了所有我能想到的组合,但都行不通。我在 '>'
和 '>>'
之间交替,因为它显然需要追加,因为它在文件名上循环,但在 if
块内都不起作用。
即使上面的这段代码也不会抛出 die
错误!它只是忽略了那些行!我想我显然遗漏了一些东西。
filenames.csv 将在找到 pdf 的目录中创建,因为 find() 在搜索时会更改目录。如果这不是您想要的,请使用绝对路径打开它(或在调用 find 之前打开它,这似乎是一个更好的主意)。
引用 File::Find::find
的文档:
Additionally, for each directory found, it will chdir() into that directory
这意味着当您在 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) = @_;
...
我在这里四处看了看,发现了类似的问题,但不完全是。如果有的话,我很抱歉,请指点一下。
我有以下代码。我正在尝试创建一个仅包含从文件名和文件名本身提取的 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
块中取出文件 open/close 和第一个打印语句,它会将那行打印到文件中,而不是块内的数据。
我已经尝试了所有我能想到的组合,但都行不通。我在 '>'
和 '>>'
之间交替,因为它显然需要追加,因为它在文件名上循环,但在 if
块内都不起作用。
即使上面的这段代码也不会抛出 die
错误!它只是忽略了那些行!我想我显然遗漏了一些东西。
filenames.csv 将在找到 pdf 的目录中创建,因为 find() 在搜索时会更改目录。如果这不是您想要的,请使用绝对路径打开它(或在调用 find 之前打开它,这似乎是一个更好的主意)。
引用 File::Find::find
的文档:
Additionally, for each directory found, it will chdir() into that directory
这意味着当您在 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) = @_;
...