Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

How do I convert long directory- and file-names in dos to the shortened 8-bit names?

Like:

C:\Program Files\Internet Explorer\ to C:\Progra~1\Intern~1\
Is there a small library file or something I can use?

Replies are listed 'Best First'.
Re: Short directory names...
by repson (Chaplain) on Jan 20, 2001 at 14:49 UTC
    Small library file? no
    Library method? yes
    use Win32::API; my $GetShortPath = new Win32::API ( "kernel32", "GetShortPathName", [' +P','P','N'], 'N' ); my $len = 100; my $short = (' ' x $len); my $long = 'c:\\program files\\microsoft office\\'; my $size = $GetShortPath->Call($long, $short, $len); print substr($short,0,$size) . "\n";
    That is probably the safest method if all versions of windows use the same function name for it, I've only got Win98 to test it on so I'm not sure what the NTs do.

    Update: Okay so it is avalible in one module. I thought it might be, it just didn't jump out at me.

      This functionality is built into the Win32 module which is packaged in the ActiveState dist of perl. All you need to do is this:
      use Win32; my $long = 'c:\\program files\\microsoft office\\'; my $short = Win32::GetShortPathName($long); print $short;
      There is also a Win32::GetLongPathName(PATHNAME) function which does the reverse.

      Also worth looking at is Jenda's Pages. He has a bunch of other Win32 "File Related" modules which are quite useful, one of which is Win32::AbsPath, another is Win32::FileOp.

      $code or die
      Using perl at
      The Spiders Web

      On Windows NT, the option to create short <acronym title="Demented Operating System">DOS</acronym> names for files can be turned off (in fact it's considered a security issue: on a web server you can request "mylong~1.asp" instead of "mylongfilename.asp" and, if certain hotfixes or service packs are not installed, get the raw source code or bypass restrictions).

      I think I'll take a look at Win32::API anyway, because there are probably lots of things you can do with it that aren't covered by any Win32 modules. How do you find out what API calls you can use and what format they require? I suppose we have to trudge round the MS site to find clues?

      $code or die
      Using perl at
      The Spiders Web

        Please check out FFI and C::Dynalib as well. They are not restricted to working on just Win32 and seem to have cleaner designs (though the APIs could use the addition of some helper functions to make things simpler).

        Documentation of many APIs in Microsoft DLLs can be found by downloading the SDK (Software Developers' Kit) from Microsoft or buying a compiler. You might be surprised how many APIs are already available from Perl via modules.

                - tye (but my friends call me "Tye")
Re: Short directory names...
by mwp (Hermit) on Jan 20, 2001 at 12:14 UTC
    I took a quick look at CPAN and wasn't able to locate a module that would simply do this for you.

    A quick answer to your question might look something like this:

    my $path = "C:\\Program Files\\Internet Explorer\\"; my @tokens = split(/\\/, $path); foreach(@tokens) { next unless length $_ > 8; s/\s//g; # remove whitespace $_ = substr($_, 0, 6) . '~1'; } $path = join("\\", @tokens);
    Although the following problems immediately become apparent:
    • If there's more than one file with the same first six characters it will need to determine whether to append ~1 or ~2 or ~3, etc.
    • It will totally annihilate directories (and files, if the path is direct) with an extension. For example, the Win32 naming schema allows you define files and directories like "My Stuff For School.January-2001" etc. I forget exactly what the new X.Y limit is (as opposed to 8.3) but it's there. If you have an extension that is greater than 3 characters, that somehow affects the appended number to the root filename. So the above might become "MYSTUF~2.JAN" if you already had a "My Stuff For School.January-2000" defined. Pain in the rear, no?

    I think that in order to answer your question better, we need to know what you're doing with the Win9x LFNs. If you don't need to do it on the fly, you're probably best off looking up the 8.3 directory name and entering it by hand. If you're running Perl in a Win9x environment, you should be able to use quotes when opening files and pipes to take advantage of Win9x's CLI. For example:

    open(OUTFILE, ">\"C:\\Temp\\Jane's Addiction.CHOPRO\"");

    So tell us, what exactly are you trying to do? =)