2012-01-19 21 views
5

Tôi đang phát triển một kịch bản mà làm cho việc sử dụng -e cờ, như trongTôi muốn làm việc với trường hợp nhạy cảm trên OS X. Có thể không?

unless (-e $fileName) 
{ 
    ... 
} 

này hoạt động tốt trên OS X. Hay nói đúng hơn, nó không hoạt động một cách chính xác. Tôi muốn nó là case- nhạy cảm. Kịch bản này cũng chạy trên máy Linux và kiểm tra -e không thành công - đúng là vì độ nhạy của chữ hoa.

Tôi đã cố gắng thực hiện một đường thay thế bằng open <FILEHANDLE, '$fileName'), nhưng có vẻ như điều đó cũng không phân biệt chữ hoa chữ thường.

Chỉnh sửa: Cảm ơn tất cả những người đã trả lời dưới đây. Tôi biết HFS + không phân biệt chữ hoa chữ thường, nhưng tôi nghĩ tôi có thể "ép buộc" bằng cách nào đó. Tôi đã kết thúc việc buộc séc bằng cách thực hiện một cái gì đó như:

opendir my($dh), $dirName or die "Couldn't open dir '$dirName'"; 
my @refFiles = readdir $dh; 
closedir $dh; 

foreach $refFile (@refFiles) 
{ 
    if ($refFile eq $refFileName) 
    { 
     $found = 1; 
    } 
} 

Câu thần chú nổi tiếng: "Nó không đẹp, nhưng nó hoạt động".

+2

'' $ fileName'' của bạn không nên sử dụng dấu ngoặc kép, và nếu có, nó sẽ sử dụng dấu ngoặc kép (trừ khi bạn ngược lại - như tôi - và trước dấu nháy đơn với 'qq '$ fileName' '). Tương tự như vậy, ký hiệu '

+4

Ngoài ra, tiêu đề của bạn nói 'phân biệt chữ hoa chữ thường' và câu hỏi cho biết 'phân biệt chữ hoa chữ thường'; bạn thật sự muốn gì? –

+1

'-e' chỉ chuyển đối số sang lệnh' stat' của hệ thống. – ikegami

Trả lời

6

Việc thiếu trường hợp nhạy cảm là do hệ thống tập tin bạn đang sử dụng (HFS +), không phải là Perl chức năng -eopen, cũng không phải là cơ bản stat (2)mở (2) cuộc gọi hệ thống.

Hệ thống tệp HFS + không phân biệt chữ hoa chữ thường theo mặc định; tuy nhiên, bạn có thể chọn tạo phân vùng HFS + nhạy cảm khi khởi tạo hệ thống tệp mới (sử dụng Tiện ích đĩa, diskutil hoặc * newfs_hfs *, v.v.): chỉ cần chọn phiên bản "Phân biệt chữ hoa chữ thường".

Tôi đã thấy các báo cáo (bị viết sai) các chương trình hoạt động sai khi chạy từ phân vùng khởi động phân biệt chữ hoa chữ thường, vì vậy tôi khuyên bạn nên sử dụng một khối lượng riêng cho công việc phân biệt chữ hoa chữ thường. Ví dụ, tạo một ảnh đĩa (tức là "ảnh đĩa thưa thớt") với hệ thống tập tin "Mac OS Extended (Case-sensitive, Journaled)" và gắn nó khi bạn cần làm công việc phân biệt chữ hoa chữ thường (ví dụ: open ~/case-sensitive.sparsebundle, sau đó cd /Volumes/Case-sensitive/foobar để làm công việc nhạy cảm của bạn từ đó).

2

Sử dụng Perl nhà xây dựng (5.14.1 - Tôi phải nâng cấp đôi khi sớm) trên hệ điều hành MacOS X 10.7.2, và kịch bản sau đây (gọi tắt là x.pl):

#!/usr/bin/env perl 
use strict; 
use warnings; 

foreach my $file (@ARGV) 
{ 
    print "OK $file\n" if (-e $file); 
} 

tôi gọi lệnh như sau:

$ perl x.pl x.pl X.pl X.PL xxx.sql 
OK x.pl 
OK X.pl 
OK X.PL 
OK xxx.sql 
$ 

(tôi xảy ra để có một tập tin xxx.sql trong thư mục hiện tại của tôi.)

Đây là một tiêu chuẩn hệ điều hành MacOS X đĩa cứng; Tôi đã không làm cho nó phân biệt chữ hoa chữ thường (tức là, tôi tin rằng, một lựa chọn).

Vì vậy, trên cơ sở các bằng chứng sẵn có của mình, các nhà điều hành -e là một cách thích hợp case-insensitive trong Perl trên hệ điều hành MacOS X.

5

Theo mặc định HFS + là case-insensitive để -e phải cũng vì nó sử dụng hệ thống tập tin nguyên thủy để thực hiện kiểm tra. Có được trường hợp nhạy cảm trên một hệ thống tập tin không phân biệt chữ hoa chữ thường là nghịch đảo và tà ác; bạn có thể có mã xác nhận không tồn tại của một tập tin với -e và sau đó có một cắt mở tiếp theo một tập tin hiện có, hoặc đã mở không thành công vì tập tin tồn tại và không đọc được/không thể đọc được.

0

Câu trả lời hiện có tập trung vào việc giải thích lý do tại sao-e trường hợp hoạt động-INensensitively trên OSX, và tại sao nó làm như vậy vì lý do tốt nói chung.

Tuy nhiên, đôi khi bạn DO muốn biết liệu một con đường tồn tại ở dạng trường chính xác, bởi vì mặc dù hệ thống tập tin có thể không quan tâm, phần mềm khác thể.

Perl chính nó là một ví dụ:
Ngày OSX, Perl (không may) chấp nhận sự thay đổi trường hợp của một tên mô-đun với tuyên bố use, vì use Thực hiện tra cứu hệ thống tập tin, đó là vốn case-insensitive. Tuy nhiên, thực tế sử dụng mô-đun đó sẽ KHÔNG hoạt động, trừ khi tên mô-đun là trường hợp-EXACT; ví dụ: perl -MData::Dumper -E 'print Dumper(666)' (OK) so với perl -Mdata::dumper -E 'print Dumper(666)' (ngắt, vì mặc dù tải mô-đun dường như thành công, các thành phần của nó, chẳng hạn như Dumper(), không thể truy cập được).

Các vấn đề trong Tóm lại: nếu con đường /FOO/BAR tồn tại trong HFS + của bạn hệ thống tập tin (trên OSX),
-e '/foo/bar' hoặc bất kỳ biến thể trường hợp đó sẽ chỉ ra rằng con đường tồn tại, và không có cách nào dễ dàng để xác định xem /foo/bar là một trường hợp đại diện chính xác hoặc, nói chung, trường hợp thực sự của con đường là gì.

Dưới đây là một ngây thơ thực hiện có sử dụng các phương pháp sau đây:

  • Đưa lợi thế của thực tế là File::Glob::bsd_glob() theo mặc định hoạt động trường nhạy cảm ngay cả trên trên OSX, có hệ thống tập tin (HFS +) là bởi đựng pin- mặc định Vô cảm.
  • Tuy nhiên, kết hợp chỉ xảy ra đối với các thành phần đường dẫn chứa mẫu thực tế, trong khi tên là tên được trả về nguyên trạng.
  • Do đó, một đường cầu được tạo từ đường dẫn đầu vào biến thành mỗi thành phần đường dẫn thành mẫu tự kết hợp, bằng cách bao quanh char thứ nhất. của mọi thành phần đường dẫn trong [] (một tập hợp chỉ khớp với chính char đó).
sub istruecasepath { 
    use File::Glob qw/bsd_glob/; 
    return defined bsd_glob join '', map { 
     m`^(//?|\.|\.\.|)$` ? 
     $_ 
     : 
     '[' . substr($_, 0, 1) . ']' . substr($_, 1) 
    } split m`(//?)`, shift; 
} 

này làm việc với các hạn chế sau:

  • con đường đầu vào không được chứa các ký tự ASCII
  • con đường đầu vào không được chứa metacharacters mẫu (ví dụ, con đường các thành phần không được chứa các ký tự bằng chữ, chẳng hạn như * hoặc [ có thể được hiểu sai dưới dạng ký tự mẫu (globbing).

Dưới đây là triển khai mạnh mẽ, bao gồm công việc bổ sung để khắc phục những hạn chế này; đầu vào dự kiến ​​như là một chuỗi Unicode:

sub istruecasepath { 
    use File::Glob qw/:bsd_glob/; 
    use Unicode::Normalize; 
    # Convert to NFD Unicode normal form, because that's how HFS+ stores names. 
    my $path_nfd_quoted = NFD shift; 
    # \-quote glob characters and '\' instances. 
    $path_nfd_quoted =~ s/[][{}*?\\]/\\$&/;             #/
    my $glob = join '', map { 
     m`^(//?|\.|\.\.|)$` ? 
     $_ 
     : 
     do { my $len = m`^\\` ? 2 : 1; '[' . substr($_, 0, $len) . ']' . substr($_, $len) } 
    } split m`(//?)`, $path_nfd_quoted; 
    return defined bsd_glob "$glob", GLOB_QUOTE; 
} 

Như một phần thưởng, đây là một biến thể mà lợi nhuận con đường trường chính xác như được lưu trữ trong hệ thống tập tin, cho một sự thay đổi trường hợp:

sub getruecasepath { 
    use File::Glob qw/:bsd_glob/; 
    use Unicode::Normalize; 
    # Convert to NFD Unicode normal form, because that's how HFS+ stores names. 
    my $path_nfd_quoted = NFD shift; 
    # \-quote glob characters and '\' instances. 
    $path_nfd_quoted =~ s/[][{}*?\\]/\\$&/;             #/
    my $glob = join '', map { 
     m`^(//?|\.|\.\.|)$` ? 
     $_ 
     : 
     do { my $len = m`^\\` ? 2 : 1; '[' . substr($_, 0, $len) . ']' . substr($_, $len) } 
    } split m`(//?)`, $path_nfd_quoted; 
    my $path_truecase = bsd_glob "$glob", GLOB_NOCASE | GLOB_QUOTE; 
    return if not defined $path_truecase; 
    # !! bsd_glob() returns a raw UTF8-encoded byte sequence that isn't 
    # !! automatically reconverted to a Unicode string, so we must do it 
    # !! manually here. 
    utf8::decode($path_truecase); 
    return $path_truecase; 
} 
Các vấn đề liên quan