0

I am using perl to do some processing of files. We copy the files from particular location and we do some processing on each file and then we copy the files to the processed location. If in the source destination if we have the folders then we will create the same structure in the destination folder as well. In the perl script we use createDirectoryw to create the folder structure.

use Win32::API;
use Encode qw(decode encode);

use Encode::Unicode;       # GBR

use Symbol qw( gensym );
use Win32API::File qw(CreateFileW OsFHandleOpen CREATE_ALWAYS GENERIC_WRITE);

$cd = Win32::API->new( 'kernel32', 'CreateDirectoryW', 'PP', 'N' );


...

..

..
my $UTF16_dirname = encode( "UTF-16LE", "$dirname\0" );
my $res = $cd->Call( $UTF16_dirname, 0 ) ;

I got the $res as 0, it didn't create the folder.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
Karthik SV
  • 99
  • 1
  • 9
  • 1
    Always use `use strict` and `use warnings`. – serenesat Feb 16 '15 at 07:12
  • added the strict and warnings, after that i got error in the below statement $cd = Win32::API->new( 'kernel32', 'CreateDirectoryW', 'PP', 'N' ); Error - Global symbol "$cd" requires explict package name – Karthik SV Feb 16 '15 at 07:32
  • Yes, you should declare `$cd` with `my` keyword because you are using `strict`. – serenesat Feb 16 '15 at 07:35
  • Your code works fine for me. I think you need show us more code (lines with $dirname initialization) – Kostia Shiian Feb 16 '15 at 08:03
  • Below is the functions used sub create_long_path($) { my $path = shift; my ( $root, $subdirs ) = $path =~ /^(\w:\\\w+)(.*)$/; $p = '\\\\?\\' . $root; # $p = $root; long_mkdir($p); my @T_subdirs = split /\\/, $subdirs; for my $subdir (@T_subdirs) { if ( $subdir ne "" ) { $p .= '\\' . $subdir; long_mkdir($p); } } } ... ..... .... sub long_mkdir($) { my $dirname = shift; # produce UTF-16LE string my $UTF16_dirname = encode( "UTF-16LE", "$dirname\0" ); my $res = $cd->Call( $UTF16_dirname, 0 ) ; return $res; } – Karthik SV Feb 16 '15 at 08:06

2 Answers2

1

Take a look at this example, it works fine for me:

use strict;
use warnings;
use Win32::API;

use Carp;
use Encode qw( encode );

Win32::API->Import(
    Kernel32 => qq{BOOL CreateDirectoryW(LPWSTR lpPathNameW, VOID *p)}
);

my $path = '\\\\?\\c:';

my $counter=255;

while ($counter)
{
    my $nextDir="\\testdir".$counter;

    $path.=$nextDir;

    mk_long_dir($path);

    $counter--;
}

sub mk_long_dir {
    my $path = shift;

    my $ucs_path = encode('UCS-2le', "$path\0");
        CreateDirectoryW($ucs_path, undef)
            or croak "Failed to create directory: '$path': $^E";

    return $path;
}

And thank to Sinan Ünür (How do I create then use long Windows paths from Perl?)

Community
  • 1
  • 1
Kostia Shiian
  • 1,024
  • 7
  • 12
  • When I worked on that question, there was no [Win32::LongPath](https://metacpan.org/pod/Win32::LongPath): It is an excellent module. See also [Creating a file using Perl on Windows in a directory the length of whose name exceeds 220 characters](http://stackoverflow.com/a/28378292/100754). – Sinan Ünür Feb 16 '15 at 12:13
  • The perl script runs fine in my environment and when i try to run in another perl environment then it fails. Got the error below , CreateFile: The system cannot find the path specified I have installed the Active perl 5.12.4 in all the environments , is there anything missing? – Karthik SV Feb 17 '15 at 07:09
  • I have created the perl exe in 64 bit machine using perl2exe and try to run the exe in 32 bit machine the CreateDirectoryW doesn't work in 32 bit but it works in 64 bit. ANy reasons? – Karthik SV Feb 17 '15 at 09:39
  • @Karthik SV : please check what is happening with procmon – Kostia Shiian Feb 17 '15 at 10:27
1

There is now an excellent module Win32::LongPath which makes it unnecessary to monkey around with (the otherwise excellent and invaluable) Win32::API.

So, use Win32::LongPath::mkdirL. If you need to pass paths to external programs, use the one obtained from Win32::LongPath::shortpathL.

Borodin
  • 126,100
  • 9
  • 70
  • 144
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339