Simulating case sensitivity for win32 files

Discussion in 'Perl Misc' started by M&M, Oct 22, 2003.

  1. M&M

    M&M Guest

    I understand that windows filesystems are case insensitive though case
    preserving. My dilema is that files on my windows server are synced
    to a linux web server where case sensitivity does matter.

    Is there a way to simulate "-f test.txt" in a case sensitive manner or
    perhaps retrieve a file's actual name? I was surprised to learn that
    neither glob("test.txt") nor <test.txt> do the job without using
    wildcards. I've searched the cpan, faqs, google groups and the
    cookbook to no avail.

    I've come up with the following but it's very inefficient for
    real_filename() to read the directory each time (especially if it is
    very large). Sure, I could cache the dir contents in a list or hash,
    but then I have the complexity of maintaining it as changes occur. It
    works, but how could it be improved? (It doesn't even address
    directories...) Certainly others have dealt with this before. Any
    suggestions?

    Thanks,

    Marco Moreno


    #!/usr/bin/perl -w

    chdir "c:/temp";

    my $file = "test.txt";

    if (-f $file and not really_exists($file)) {
    my $realname = real_filename($file);
    warn "Renaming $realname to $file.\n";
    rename $realname, $file or die "Can't rename $realname: \n";
    }

    sub really_exists {
    my $filename = shift;
    return $filename eq real_filename($filename) ? 1 : 0;
    }

    sub real_filename {
    my $filename = shift;
    opendir DIR, "." or die "Can't readdir: $!";
    (my $realname) = grep { $filename =~ /^${_}$/i } readdir DIR;
    closedir DIR;
    return $realname;
    }
    M&M, Oct 22, 2003
    #1
    1. Advertising

  2. M&M () wrote:
    : I understand that windows filesystems are case insensitive though case
    : preserving. My dilema is that files on my windows server are synced
    : to a linux web server where case sensitivity does matter.

    : Is there a way to simulate "-f test.txt" in a case sensitive manner or
    : perhaps retrieve a file's actual name? I was surprised to learn that

    This sort of information is available in windows, so I would assume that
    the various win32 module(s) would have some way to get the information.
    Malcolm Dew-Jones, Oct 23, 2003
    #2
    1. Advertising

  3. M&M

    Sisyphus Guest

    M&M wrote:

    >
    > #!/usr/bin/perl -w
    >
    > chdir "c:/temp";
    >
    > my $file = "test.txt";
    >
    > if (-f $file and not really_exists($file)) {
    > my $realname = real_filename($file);
    > warn "Renaming $realname to $file.\n";
    > rename $realname, $file or die "Can't rename $realname: \n";
    > }
    >
    > sub really_exists {
    > my $filename = shift;
    > return $filename eq real_filename($filename) ? 1 : 0;
    > }
    >
    > sub real_filename {
    > my $filename = shift;
    > opendir DIR, "." or die "Can't readdir: $!";
    > (my $realname) = grep { $filename =~ /^${_}$/i } readdir DIR;
    > closedir DIR;
    > return $realname;
    > }



    I think one improvement would be to create an array containing the
    actual names of the files so that you aren't constantly re-reading
    through the directory.

    @real_filenames = grep { -f "$_"} readdir DIR;
    # assumes the opened dir is "."
    # In general: grep {-f "$dir/$_"} readdir DIR;

    really_exists() could then look something like this:

    sub really_exists {
    my $filename = shift;
    for(@real_filenames) {
    if($_ eq $filename) {return 1}
    if(lc($_) eq lc($filename)) {return 2}
    }
    return 0;
    }

    Hth.

    Cheers,
    Rob


    --
    To reply by email u have to take out the u in kalinaubears.
    Sisyphus, Oct 23, 2003
    #3
  4. M&M

    Roy Johnson Guest

    (M&M) wrote in message news:<>...
    > It works, but how could it be improved? (It doesn't even address
    > directories...) Certainly others have dealt with this before. Any
    > suggestions?


    It can surely be improved. First of all, you call real_filename twice
    every time you encounter it. Get rid of the really_exists sub. You
    need the real filename, anyway, so having the really_exists sub throw
    it away works against you.
    if (-f $file) {
    my $realname = real_filename($file);
    if ($file ne $realname) {
    #...renaming...

    Now, in real_filename, you've chosen to grep through the entire
    directory, with no possibility of short-circuiting. Ouch. Also,
    caching is not so difficult to add:
    my %file_cache;
    sub real_filename {
    my $filename = lc(shift); ## Compare as lowercase only
    unless (exists $file_cache{$filename}) {
    opendir DIR, '.' or die "Can't readdir: $!";
    while (my $f = readdir DIR) {
    if ($filename eq lc($f)) {
    $file_cache{$filename} = $f;
    last; ## When you find it, stop reading!
    }
    }
    closedir DIR;
    }
    return $file_cache{$filename};
    }
    Roy Johnson, Oct 23, 2003
    #4
  5. M&M

    Roy Johnson Guest

    I just realized that the caching I suggested is pointless, since you
    immediately rename the file. Of course, you can update the cache each
    time you do a rename.

    If you're only going to see each filename once, there's no point in
    maintaining a cache. Just slurp the whole directory list into a hash
    mapping lc(name)=>name, and then use it to lookup the file names when
    you see them.

    If you're going to rename all the files that aren't equal to their
    canonical names (I'm guessing lowercase?), just do the rename for
    every file, and don't worry about those that don't change.

    I'm not real sure how you're planning to work with all the files, but
    I hope some of these thoughts helped.
    Roy Johnson, Oct 23, 2003
    #5
  6. Malcolm Dew-Jones () wrote:
    : M&M () wrote:
    : : or
    : : perhaps retrieve a file's actual name?

    So, did you try Win32::GetLongPathName yet?
    Malcolm Dew-Jones, Oct 24, 2003
    #6
  7. M&M

    M&M Guest

    (Roy Johnson) wrote in message news:<>...

    I appreciate the comments, but this isn't really what I'm after. I'm
    looking for a case sensitive "-f" option so I can do something like
    this:

    if (-f "/Very/Long/Path/To/file.htm")...

    Or at least use a function to retrieve the native pathname from the
    os:

    print realname("c:/very/long/path/to/file.htm");

    yeilding

    C:/Very/Long/Path/To/file.htm

    I searched all the win32 modules on cpan, but I found nothing that
    seems to do this. I posted the sample code merely as a proof of
    concept that it is theoretically possible though highly inefficient
    and impractical - nor does it handle case sensitivity of directories.
    Using my method, I would need to read /, /Very, /Very/Long,
    /Very/Long/Path.... It quickly becomes obvious that reading each
    directory is not the solution. (I hope!)

    And caching really isn't an option for me because it assumes that
    files will not change. Even if the script handled the complexity of
    maintaining the cache as it changed files, it doesn't take into
    account multiple threads/processes or file changes by external
    processes.

    Marco Moreno
    M&M, Oct 24, 2003
    #7
  8. M&M

    M&M Guest

    Ahhh!!! I found Win32::GetLongPathName() that returns the actual
    path! I didn't realize this was in the Win32 core module.

    Marco
    M&M, Oct 24, 2003
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Harry Whitehouse
    Replies:
    0
    Views:
    290
    Harry Whitehouse
    Sep 15, 2004
  2. Replies:
    0
    Views:
    454
  3. Kev
    Replies:
    15
    Views:
    832
    Lunchbox G4
    Jan 3, 2005
  4. Roy Schestowitz

    Case Sensitivity in Linux Server

    Roy Schestowitz, Mar 23, 2005, in forum: HTML
    Replies:
    10
    Views:
    735
    Roy Schestowitz
    Mar 24, 2005
  5. asqui
    Replies:
    0
    Views:
    251
    asqui
    Aug 17, 2004
Loading...

Share This Page