12

数千のファイルを含むフォルダーを通過する perl スクリプトがあります。

スクリプトを書き始めたとき、私は perl の File::Find 関数を知らなかったので、構造内のすべてのファイルを一覧表示するために、次の行に沿って何かを使用しました。

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

ただし、外部プログラムを起動する代わりに、perl からこれを実行しようと考えました。(File::Find の使い方を学びたいという以外に、この変更を行う本当の理由はありません。)

File::Find find 関数のセマンティクスを学ぼうとして、コマンド ラインでいくつかのことを試し、出力を find の出力と比較しました。

奇妙なことに、プログラム find が見つけたファイルが 1 つありますが、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」のサイズ制限に達していますか? ファイルはほぼ 4 GB で、選択範囲内で最大です。

または、私のテスト (-f の場合) の選択が不十分ですか?

編集[ファイルを統計しようとしています]:

大きなファイルが失敗する

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
4

1 に答える 1

10

ちょっとしたグーグルに基づいて、あなたのperlインタープリターは大きなファイルのサポートでコンパイルされていないように見えます.2GBをstat超える-fファイルでは失敗します.

これに該当するかどうかを確認するには、次を実行します。

perl -V | grep "uselargefiles|FILE_OFFSET_BITS"

perl が大きなファイルをサポートしている場合、出力は と のようuselargefiles=defineになり-D_FILE_OFFSET_BITS=64ます。そうでない場合は、perl が大きなファイルをサポートしていない可能性があります。

たとえ単にstating ファイルであっても、なぜ大きなファイルのサポートが必要なのか、やや不可解かもしれません。根本的な問題は、32 ビット バージョンのstat(2)システム コールが、偽のサイズを返すのではなく、EOVERFLOW2GB を超えるファイルに適用された場合に単純に失敗することです。

イーオーバーフロー」

( stat ()) pathは、タイプoff_tでサイズを表すことができないファイルを参照しています。これは、 -D_FILE_OFFSET_BITS=64を指定せずに 32 ビット プラットフォームでコンパイルされたアプリケーションが、(1<<31)-1ビットを超えるサイズのファイルに対してstat () を呼び出した場合に発生する可能性があります。"

技術的には、そのエラーを受け取ることは、指定されたファイルが存在することを示すのに十分なはずです (ただし、それは本当に巨大なディレクトリである可能性もあります)。何も返しません。

(編集:池上がコメントで正しく指摘しているように、stat(2) 呼び出しが失敗した場合は 0 または 1 ではなく-f戻り、失敗の原因となったエラー コードに設定します。したがって、すべてのディレクトリ エントリがサイズが 2GB を超えるファイルはファイルであり、チェックするようなことを行うことができます。)undef$!-f $_ or (not defined -f _ and $!{EOVERFLOW})

于 2012-12-26T14:02:52.003 に答える