2012-01-19 9 views
5

Estoy desarrollando un script que hace uso de la bandera -e, como enQuiero -e trabajar con mayúsculas y minúsculas en OS X. ¿Es posible?

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

Esto funciona bien en OS X. O, más bien, que no funciona correctamente. Quiero que sea case- sensible. La secuencia de comandos también se ejecuta en una máquina Linux y la comprobación -e falla, ¡correctamente! Debido a la sensibilidad de mayúsculas y minúsculas.

Intenté hacer una ruta alternativa con open <FILEHANDLE, '$fileName'), pero parece que eso también es insensible a mayúsculas y minúsculas.

Editar: Gracias a todos los que respondieron a continuación. Sé que HFS + no distingue entre mayúsculas y minúsculas, pero pensé que podría "forzarlo" de alguna manera. Hice terminar forzando un cheque por hacer algo como:

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; 
    } 
} 

El famoso lema: "No es bonito, pero funciona."

+2

Su ''$ fileName'' no debe usar comillas, y si lo hace, debe usar comillas dobles (a menos que sea perverso, como yo, y preceda las comillas simples con' qq' $ fileName ' '). Del mismo modo, la notación '

+4

Además, su título dice 'distingue entre mayúsculas y minúsculas' y la pregunta dice 'insensible a mayúsculas y minúsculas'; ¿Qué es lo que realmente quieres? –

+1

'-e' simplemente pasa el argumento a la llamada' stat' de su sistema. – ikegami

Respuesta

6

La falta de sensibilidad caso se debe al sistema de archivos que está utilizando (HFS +), no el Perl funciona -e y open, ni los subyacentes stat (2) y abiertas (2) llamadas al sistema.

El sistema de archivos HFS + no distingue entre mayúsculas y minúsculas por defecto; sin embargo, puede optar por crear un volumen HFS + sensible a mayúsculas al inicializar un nuevo sistema de archivos (usando Disk Utility, diskutil, o * newfs_hfs *, etc.): simplemente seleccione la versión "Case-sensitive".

He visto informes de programas (mal escritos) que funcionan mal cuando se ejecutan desde un volumen de inicio sensible a las mayúsculas y minúsculas, por lo que le aconsejo que use un volumen separado para su trabajo que distingue entre mayúsculas y minúsculas. Por ejemplo, cree una imagen de disco (es decir, "imagen de conjunto de discos dispersos") con un sistema de archivos "Mac OS ampliado (sensible a mayúsculas y minúsculas)" y móntelo cuando necesite realizar su trabajo (por ejemplo, open ~/case-sensitive.sparsebundle, luego cd /Volumes/Case-sensitive/foobar para hacer su trabajo sensible a mayúsculas desde allí).

2

El uso de un Perl construido en casa (5.14.1 - Debo actualizar en algún momento pronto) en MacOS X 10.7.2, y el siguiente script (llamado x.pl):

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

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

invoqué el comando como:

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

(Resulta que tengo un archivo xxx.sql en mi directorio actual.)

se trata de un disco duro estándar de Mac OS X; No lo hice sensible a mayúsculas y minúsculas (que es, creo, una opción).

Así, sobre la base de mi evidencia disponible, el operador -e es apropiada entre mayúsculas y minúsculas en Perl en MacOS X.

5

Por defecto HFS + es sensible a las mayúsculas por lo -e debe ser así, ya que utiliza el sistema de archivos primitivos para hacer el control. Tener que ser sensible a las mayúsculas y minúsculas en un sistema de archivos insensible a mayúsculas y minúsculas sería perverso y malvado; podría tener un código que confirme la inexistencia de un archivo con -e y luego tener una apertura posterior truncar un archivo existente, o tener un error abierto porque el archivo existe y es ilegible/no escribible.

0

Las respuestas existentes se centran en explicar por qué-e funciona case-INsensitively en OSX, y por qué lo hace por buenas razones en general.

Sin embargo, veces te quieren saber si existe un camino en forma exacta de mayúsculas, porque a pesar de que el sistema de archivos no puede cuidar, otro software de puede.

Perl en sí es un ejemplo:
En OSX, Perl (por desgracia) acepta variaciones de caso de un nombre de módulo con la declaración use, porque use realiza búsquedas sistemas de ficheros, que son sensibles a mayúsculas inherentemente. Sin embargo, realmente usando ese módulo NO funcionará, a menos que el nombre del módulo sea CASO-EXACTO; por ejemplo: perl -MData::Dumper -E 'print Dumper(666)' (OK) frente a perl -Mdata::dumper -E 'print Dumper(666)' (se rompe, porque aunque cargando el módulo parece tener éxito, no se puede acceder a sus elementos, como Dumper()).

El problema en pocas palabras: si existe camino /FOO/BAR en su HFS + sistema de archivos (en OSX),
-e '/foo/bar' o cualquier variación caso del mismo indicará que existe el camino, y no hay manera fácil de determinar si /foo/bar es un caso -representación exacta o, más en general, cuál es el verdadero caso de la ruta.

Aquí hay una aplicación ingenua que utiliza el siguiente enfoque:

  • se aprovecha del hecho de que File::Glob::bsd_glob() por defecto actúa casos y con sensibilidad incluso en el OSX, cuyo sistema de archivos (HFS +) es por caso- por defecto Insensible.
  • Sin embargo, la coincidencia solo se produce para los componentes de ruta que contienen un patrón real , mientras que nombres literales se devuelven tal cual.
  • Por lo tanto, un globo se construye a partir de la ruta de entrada que convierte cada componente de trayectoria en un patrón de auto coincidencia, encerrando el primer carácter. de cada componente de ruta en [] (un conjunto que solo coincide con ese carácter en sí).
sub istruecasepath { 
    use File::Glob qw/bsd_glob/; 
    return defined bsd_glob join '', map { 
     m`^(//?|\.|\.\.|)$` ? 
     $_ 
     : 
     '[' . substr($_, 0, 1) . ']' . substr($_, 1) 
    } split m`(//?)`, shift; 
} 

Esto funciona con las siguientes limitaciones:

  • la ruta de entrada no debe contener caracteres no ASCII
  • la ruta de entrada no debe contener metacaracteres patrón (es decir, el camino los componentes no deben contener caracteres literales, como * o [, que podrían interpretarse erróneamente como caracteres de patrón (globbing).

Aquí hay una implementación robusta , que implica trabajo adicional para superar estas limitaciones; Se espera que la entrada como una cadena 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; 
} 

Como beneficio adicional, aquí está una variante que vuelve la trayectoria exacta de mayúsculas tal como se almacena en el sistema de archivos, dada una variación caso:

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; 
} 
Cuestiones relacionadas