在Windows上使用Perl在名称长度超过220个字符的目录中创建文件
我遇到一个问题,无法在名称长度超过220个字符的目录下创建文件 以下是一个测试脚本,它至少在我的机器上复制观察到的行为:在Windows上使用Perl在名称长度超过220个字符的目录中创建文件,windows,perl,ntfs,Windows,Perl,Ntfs,我遇到一个问题,无法在名称长度超过220个字符的目录下创建文件 以下是一个测试脚本,它至少在我的机器上复制观察到的行为: use warnings; use strict; use Win32::LongPath; print system ('rmdir /s /q test'); mkdirL('test'); for my $i (200 .. 255) { my $dir_name = 'test/' . sprintf("%04d", $i) . ('a' x ($i-4)
use warnings;
use strict;
use Win32::LongPath;
print system ('rmdir /s /q test');
mkdirL('test');
for my $i (200 .. 255) {
my $dir_name = 'test/' . sprintf("%04d", $i) . ('a' x ($i-4));
mkdirL($dir_name);
openL(\my $fh, '>', "$dir_name/" . ('_' x 200) . '.txt') or die "$^E";
print $fh 'Hello!';
# closeL $fh;
}
此脚本将在0220aaaa…aaa/
下创建一个\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
是否存在此问题的原因?如何更改脚本,以便在所有目录中创建*.txt
文件
更新:
脚本在运行时不会死掉或产生任何错误消息
更新2:
与其他问题一样,此问题在中没有答案,其答案清楚地表明,此路径长度限制是Windows问题,而不是NTFS问题。NTFS允许长度最多为32K个字符的路径
事实上,我的测试脚本能够创建最多255个字符的目录(正如NTFS规范所预期的那样),当目录名超过220个字符时,似乎不可能在目录中存储文件。TL;博士
问题的根源是您试图验证文件是否已创建的方法。有关更多信息,请阅读下面的详细说明
事实如下:
perl
在使用mkdirL
或openL
调用时不会给出任何错误
perl
可以使用openL
打开创建的文件并读取内容
因此,问题在于,无论您使用什么工具,要么使用ANSI版本的Windows API调用,要么指定相对路径,或者两者的组合,因此它们的路径限制为260个字符
为了测试这一点,我在D:\t
下运行了脚本。瞧,当$i=250
时,GVim无法打开文件:
D:\t
是四个字符,\test
是另外五个字符。因此,250+9=259,当您添加另一个\
时,它会点击260
使用shortpathL
试试这个:
#!/usr/bin/env perl
use strict;
use warnings;
use Win32::LongPath;
`cmd /c rd /s /q test`;
mkdirL('test') or die "$^E";
my $dir_length = 255;
my $dir_name = 'test/'
. sprintf("%04d", $dir_length)
. ('a' x ($dir_length - 4))
;
mkdirL($dir_name) or die "$^E";
my $file_name = "$dir_name/" . ('z' x 200) . '.txt';
printf "% 3d\n", length $file_name;
openL(\my $fh, '>', $file_name) or die "$^E";
print $fh "Hello!\n" or die "$^E";
close $fh or die "$^E";
system 'notepad.exe', shortpathL($file_name);
您将获得:
因此,请为无法使用Unicode接口的任何外部程序提供短路径
冗长的解释
现在我已经有机会在一台计算机上实际尝试了这一点,我无法复制这个问题
以下是我使用的代码:
#!/usr/bin/env perl
use strict;
use warnings;
use Win32::LongPath;
`cmd /c rd /s /q test`;
mkdirL('test')
or die "$^E";
for my $i (200 .. 255) {
my $dir_name = 'test/' . sprintf("%04d", $i) . ('a' x ($i-4));
mkdirL($dir_name) or die "$^E";
my $file_name = "$dir_name/" . ('_' x 200) . '.txt';
printf "% 3d\n", length $file_name;
openL(\my $fh, '>', $file_name)
or die "$^E";
print $fh 'Hello!' or die "$^E";
close $fh or die "$^E";
}
以下是输出:
C:\…\Temp> perl tt.pl
410
411
412
413
414
415
…
460
461
462
463
464
465
产出:
…
459
Hello!
460
Hello!
461
Hello!
462
Hello!
463
Hello!
464
Hello!
465
Hello!
…
459
你好
460
你好
461
你好
462
你好
463
你好
464
你好
465
你好
因为Win32::LongPath
内部规范化了路径,所以它们遵循“要指定扩展长度路径,请使用“\\?\”
前缀”建议,然后使用Unicode版本的API调用,例如,openL
不会遇到此类问题
在该函数的ANSI版本中,名称仅限于MAX\u PATH
个字符。要将此限制扩展到32767个宽字符,请调用该函数的Unicode版本,并在路径前添加“\\?\”
。有关详细信息,请参阅
如何验证文件是否已正确创建?
另外,请参阅“”,了解有关的解释,是否收到任何错误消息?了解Windows上的问题:@Sobrique,此最大路径长度是Windows问题,而不是NTFS问题
Win32::LongPath
专门设计用于解决Windows问题并充分利用NTFS的潜力。此外,脚本将创建目录,直到其长度为255个字符,在目录中创建文件似乎是不可能的;Windows长路径支持不允许正斜杠。(当然,Win32::LongPath可能正在为您进行转换。)正是这样:我/Perl创建了这些文件,但试图使用文件资源管理器查看它们(正如您所指出的,我应该知道的),这是一个毫无意义、徒劳的练习。
…
459
Hello!
460
Hello!
461
Hello!
462
Hello!
463
Hello!
464
Hello!
465
Hello!