2012-12-26 26 views
12

Tôi có một tập lệnh perl đi qua một thư mục với một vài nghìn tệp.perl -f kiểm tra không xác định được tệp

Khi tôi bắt đầu viết kịch bản tôi đã không biết File perl :: Tìm chức năng, vì vậy để liệt kê tất cả các tập tin trong cấu trúc tôi đã sử dụng một cái gì đó dọc theo dòng:

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

Bây giờ tuy nhiên Tôi nghĩ rằng tôi sẽ cố gắng làm điều này từ perl thay vì tung ra một chương trình bên ngoài. (Không có lý do thực sự để thực hiện thay đổi này ngoài việc muốn học cách sử dụng Tệp :: Tìm.)

Cố gắng tìm hiểu ngữ nghĩa của Tệp :: Tìm chức năng tìm kiếm Tôi đã thử một vài điều trên dòng lệnh và so sánh đầu ra để tìm.

Thật kỳ lạ là có 1 tệp mà chương trình tìm thấy nhưng hàm perl bỏ qua.

Find hoạt động:

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 thất bại:

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 

Thay đổi để loại trừ thư mục chứ không phải là bao gồm các file hoạt động:

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 

Chỉ sự khác biệt giữa các tập tin có kích thước:

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 trên máy trong câu hỏi là cũ nhưng không cổ:

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. 

Đây có phải là một lỗi được biết đến hoặc một cái gì đó?

Hoặc tôi có đạt đến giới hạn kích thước '-f' không? Các tập tin là gần như 4GB và lớn nhất trong việc lựa chọn.

Hoặc thử nghiệm của tôi (nếu -f) được chọn kém?

EDIT [cố gắng để stat file]:

Big tập tin thất bại

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

tập tin nhỏ làm việc

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; 

Binary 'stat' hoạt động trên cả file

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 

Ngoài ra:

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 

Vấn đề "giải quyết":

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 

trình:

# 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 
+1

Tò mò. Bạn có thể [stat] (http://perldoc.perl.org/functions/stat.html) các tập tin và cho chúng tôi thấy những gì nó trở về? –

+0

Chỉ số có vẻ không thành công, tôi sẽ chỉnh sửa bài đăng và thêm kết quả của các bài kiểm tra của tôi. – azzid

+1

Không thành công? Như trong, nó trả về một danh sách trống? –

Trả lời

10

cơ sở d trên a bit của Googling, có vẻ như trình thông dịch perl của bạn chưa được biên dịch với large file support, gây ra stat (và bất kỳ kiểm tra tệp nào dựa trên nội bộ, bao gồm -f) để không cho tệp lớn hơn 2GB.

Để kiểm tra xem đây là trường hợp, chạy:

perl -V | grep "uselargefiles|FILE_OFFSET_BITS" 

Nếu perl của bạn có hỗ trợ tập tin lớn, sản lượng sẽ hiển thị một cái gì đó giống như uselargefiles=define-D_FILE_OFFSET_BITS=64. Nếu không, có khả năng là bạn perl không hỗ trợ các tệp lớn.

Có thể hơi khó hiểu tại sao cần hỗ trợ tệp lớn ngay cả đối với các tệp ing stat ing. Vấn đề cơ bản là phiên bản 32-bit của cuộc gọi stat(2) hệ thống, chứ không phải trở về một kích thước không có thật, chỉ đơn giản là không thành công với EOVERFLOW nếu áp dụng vào một tập tin lớn hơn 2GB:

"EOVERFLOW

(stat()) đường đề cập đến một tập tin có kích thước không thể được đại diện trong các loại off_t. Điều này có thể xảy ra khi một ứng dụng biên soạn trên một nền tảng 32-bit mà không -D_FILE_OFFSET_BITS = 64 gọi stat() trên tệp có kích thước vượt quá (1 < < 31) -1 bit."

Về mặt kỹ thuật, nhận rằng lỗi nên là đủ để cho biết rằng các tập tin có tên không tồn tại (mặc dù tôi đoán nó có thể là một thư mục thực sự khổng lồ quá), nhưng perl là không đủ thông minh để nhận ra rằng — nó chỉ thấy rằng stat thất bại, và do đó trả về không có gì

(Edit:. Như Ikegami ghi nhận một cách chính xác trong các ý kiến, -f lợi nhuận undef chứ không phải là 0 hoặc 1 nếu stat (2) gọi thất bại, và bộ $! vào mã lỗi thứ gây ra sự thất bại. Vì vậy, nếu bạn không nhớ giả định rằng tất cả các mục nhập thư mục có kích thước> 2GB là các tệp, bạn có thể làm điều gì đó như -f $_ or (not defined -f _ and $!{EOVERFLOW}) để kiểm tra.)

+5

Nó không trả lại gì; nó trả về undef (error) thay vì 0 (không phải là một tệp đơn giản) và đặt '$!' thành 'EOVERLFLOW'. Bạn có thể kiểm tra tràn bằng cách kiểm tra '$! {EOVERFLOW}' khi '-f' trả về undef. – ikegami

+0

Bạn, thưa bạn, rất chính xác. Bạn có thể rút tiền bằng bia bất cứ khi nào tôi có thể giao hàng. ;) Cảm ơn bạn! – azzid

+1

@azzid: Không sao cả. Chúng ta có thể thấy về bia nếu tôi từng có lý do để ở gần Linköping. :) –

Các vấn đề liên quan