Perl -f check无法识别文件



我有一个perl脚本,它遍历一个包含数千个文件的文件夹。

当我开始编写脚本时,我不知道perl File::Find函数,所以为了列出结构中的所有文件,我使用了:

一行。
open (FILES, "$FIND $FOLDER -type f |");
while (my $line = <FILES>) {...}

现在,然而,我想我会尝试从perl而不是启动一个外部程序来做这个。(除了想要学习使用File::Find之外,没有真正的理由进行此更改。)

试图学习File::Find Find函数的语义,我在命令行上尝试了一些事情,并将输出与Find的输出进行了比较。

奇怪的是,有一个文件是find程序找到的,但是perl函数跳过了。

找到工作:

machine:~# find /search/path -type f | grep UNIQ
/search/path/folder/folder/UNIQ/movie_file_015.MOV
/search/path/folder/folder/UNIQ/movie_file_145.MOV
/search/path/folder/folder/UNIQ/Thumbs.db
machine:~# find /search/path -type f | wc -l
    6439
Perl失败:

machine:~# perl -e 'use File::Find; find(sub { print $File::Find::name . "n" if -f }, "/search/path");' | grep  UNIQ
/search/path/folder/folder/UNIQ/movie_file_145.MOV
/search/path/folder/folder/UNIQ/Thumbs.db
machine:~# perl -e 'use File::Find; find(sub { print $File::Find::name . "n" if -f }, "/search/path");' | wc -l
    6438

更改为排除文件夹而不是包含文件工作:

machine:~# perl -e 'use File::Find; find(sub { print $File::Find::name . "n" unless -d }, "/search/path");' | grep  UNIQ
/search/path/folder/folder/UNIQ/movie_file_015.MOV
/search/path/folder/folder/UNIQ/movie_file_145.MOV
/search/path/folder/folder/UNIQ/Thumbs.db

两个文件的唯一区别是大小:

machine:~# ls -l /search/path/folder/folder/UNIQ/
total 4213008
-rw-rw-r--    1 user users    4171336632 May 27  2012 movie_file_015.MOV
-rw-rw-r--    1 user users    141610616 May 27  2012 movie_file_145.MOV
-rw-rw-r--    1 user users       20992 May 27  2012 Thumbs.db

问题机器上的Perl是旧的,但不是古老的:

machine:~# perl -version
This is perl, v5.8.8 built for sparc-linux
Copyright 1987-2006, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

这是一个已知的错误还是什么?

或者我是否达到了'-f'的大小限制?这个文件差不多有4gb,是所有文件中最大的。

还是我的测试(if -f)选择不当?

EDIT[尝试启动文件]:

大文件失败

machine:~# perl -e 'use Data::Dumper; print Dumper(stat("/search/path/folder/folder/UNIQ/movie_file_015.MOV"));'

小文件工作

machine:~# perl -e 'use Data::Dumper; print Dumper(stat("/search/path/folder/folder/UNIQ/movie_file_145.MOV"));'
$VAR1 = 65024;
$VAR2 = 19989500;
$VAR3 = 33204;
$VAR4 = 1;
$VAR5 = 1004;
$VAR6 = 100;
$VAR7 = 0;
$VAR8 = 141610616;
$VAR9 = 1349281585;
$VAR10 = 1338096718;
$VAR11 = 1352403842;
$VAR12 = 16384;
$VAR13 = 276736;

二进制'stat'在两个文件上都有效

machine:~# stat /search/path/folder/folder/UNIQ/movie_file_015.MOV
  File: "/search/path/folder/folder/UNIQ/movie_file_015.MOV"
  Size: 4171336632  Blocks: 8149216    IO Block: 16384  Regular File
Device: fe00h/65024d        Inode: 19989499    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1004/user)   Gid: (  100/   users)
Access: 2012-10-03 18:11:05.000000000 +0200
Modify: 2012-05-27 07:23:34.000000000 +0200
Change: 2012-11-08 20:44:02.000000000 +0100
machine:~# stat /search/path/folder/folder/UNIQ/movie_file_145.MOV
  File: "/search/path/folder/folder/UNIQ/movie_file_145.MOV"
  Size: 141610616   Blocks: 276736     IO Block: 16384  Regular File
Device: fe00h/65024d        Inode: 19989500    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1004/user)   Gid: (  100/   users)
Access: 2012-10-03 18:26:25.000000000 +0200
Modify: 2012-05-27 07:31:58.000000000 +0200
Change: 2012-11-08 20:44:02.000000000 +0100

:

machine:~# perl -e 'stat("/search/path/folder/folder/UNIQ/movie_file_145.MOV"); print $! . "n";'
Bad file descriptor
machine:~# perl -e 'stat("/search/path/folder/folder/UNIQ/movie_file_015.MOV"); print $! . "n";'
Value too large for defined data type

EDIT2 :

# perl -V | grep "uselargefiles|FILE_OFFSET_BITS"
config_args='-Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=sparc-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.8 -Dsitearch=/usr/local/lib/perl/5.8.8 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Dstatic_ext=B ByteLoader GDBM_File POSIX re -Dusemymalloc -Uuselargefiles -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.8 -Dd_dosuid -des'
useperlio=define d_sfio=undef uselargefiles=undef usesocks=undef
"解决"

问题:

machine:~# perl -e 'stat("/search/path/folder/folder/UNIQ/movie_file_015.MOV"); print $!{EOVERFLOW} . "n";'
92
machine:~# perl -e 'stat("/search/path/folder/folder/UNIQ/movie_file_145.MOV"); print $!{EOVERFLOW} . "n";'
0

:

# perl -e 'use File::Find; find(sub { print $File::Find::name . "n" if -f or ( $!{EOVERFLOW} > 0 and not -d) }, "/search/path");' | grep UNIQ
/search/path/folder/folder/UNIQ/movie_file_015.MOV 
/search/path/folder/folder/UNIQ/movie_file_145.MOV 
/search/path/folder/folder/UNIQ/Thumbs.db

根据一点google搜索,看起来您的perl解释器没有使用大文件支持编译,导致stat(以及任何内部依赖于它的文件测试,包括-f)对于大于2GB的文件失败。

执行命令

检查是否为这种情况。
perl -V | grep "uselargefiles|FILE_OFFSET_BITS"

如果您的perl支持大文件,输出应该显示类似uselargefiles=define-D_FILE_OFFSET_BITS=64的内容。如果不支持,说明您的perl可能不支持大文件。

这可能有点令人费解,为什么需要大文件支持,即使只是stat文件。潜在的问题是32位版本的stat(2)系统调用,而不是返回一个伪造的大小,如果应用于大于2GB的文件,则使用EOVERFLOW会失败:

" EOVERFLOW

(stat()) path是指不能用类型off_t表示大小的文件。当在32位平台上编译的应用程序没有-D_FILE_OFFSET_BITS=64时,在大小超过(1<<31)-1位的文件上调用stat(),就会发生这种情况。"

从技术上讲,接收到错误应该足以表明命名文件确实存在(尽管我猜它也可能是一个真正巨大的目录),但是perl不够聪明,无法意识到—它只看到stat失败,因此不返回任何东西。

(Edit:正如ikegami在注释中正确指出的那样,如果stat(2)调用失败,-f返回undef而不是0或1,并将$!设置为导致失败的错误代码。因此,如果您不介意假设所有大小> 2GB的目录项都是文件,您可以执行-f $_ or (not defined -f _ and $!{EOVERFLOW})之类的命令来检查它。

相关内容

  • 没有找到相关文章

最新更新