在 Windows 上使用 Perl 在名称长度超过 220 个字符的目录中创建文件

2024-03-03

我遇到一个问题,无法在名称长度超过 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));
  mkdirL($dir_name);

  openL(\my $fh, '>', "$dir_name/" . ('_' x 200) . '.txt') or die "$^E";
  print $fh 'Hello!';
# closeL $fh;
}

该脚本将创建一个_________.....___.txt文件下0220aaaa...aaa/但不低于0221aaaa...aaa/.

这个问题有原因吗?我该如何更改脚本以便*.txt文件是否在所有目录中创建?

Update:

该脚本在运行时不会终止或产生任何错误消息。

更新2:

这个问题确实not已经有答案了为什么 Windows 中存在 260 个字符的路径长度限制? https://stackoverflow.com/questions/1880321/why-does-the-260-character-path-length-limit-exist-in-windows正如另一个问题及其答案清楚地表明,这个路径长度限制是一个 Windows 问题,而不是一个问题NTFS问题。 NTFS 允许路径长度最多为 32K 字符。

事实上,我的测试脚本能够创建最多 255 个字符的目录(正如 NTFS 规范所期望的那样),当目录名超过 220 个字符时,似乎不可能在目录中存储文件。


TL;DR

问题的根源在于您尝试验证文件是否已创建的方法。欲了解更多信息,请阅读下面的详细说明。

以下是事实:

  1. perl使用时不会出现任何错误mkdirL or openL calls.
  2. perl可以打开创建的文件并读取内容,使用openL.

因此,问题是由于无论您使用什么工具,要么使用 ANSI 版本的 Windows API 调用,要么指定相对路径,要么两者的组合,因此它们的路径被限制为 260 个字符。

为了测试这一点,我在下面运行了脚本D:\t。你瞧,GVim 无法打开文件$i = 250:

D:\t是四个字符,\test还有五个。因此,250 + 9 =259,这击中了260当你添加另一个的那一刻\.

Using 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 接口的任何外部程序提供短路径。

长篇大论的解释

现在我有机会实际尝试一下64位Windows 8.1系统 http://blog.nu42.com/2014/11/64-bit-perl-5201-with-visual-studio.html,我无法复制这个问题。

这是我使用的代码:

#!/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  

我还附上了一些屏幕截图:

现在,我可以报告资源管理器在导航到任何目录时遇到问题C:\...\Temp\test\0220aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

并且GVim无法打开后续目录中的文件。那是,system 'c:/.../gvim.exe', $file_name;从脚本结果中发出

大概 GVim 会遇到以下情况命名文件、路径和命名空间 https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx

因为你不能使用"\\?\"带有相对路径的前缀,相对路径始终限制为 MAX_PATH 字符总数。

巧合的是,我的路径长度%TEMP%目录恰好有 33 个字符。添加到 5(长度\test),我们有 38。将其添加到 221,我们得到259。现在,当您向该字符串添加目录分隔符时,您会点击260.

这让我想到,您正在创建的工作目录的完整路径的长度是多少test?

更好的消息是,perl能够读回所有写入的内容:

#!/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 (220 .. 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";

    openL(\my $in, '<', $file_name)
        or die "$^E";

    print <$in>, "\n" or die "$^E";

    close $in or die "$^E";
}

outputs:


…
 459  
Hello!
 460  
Hello!
 461  
Hello!
 462  
Hello!
 463  
Hello!
 464  
Hello!
 465  
Hello!  

Because Win32::LongPath在内部标准化路径,以便它们遵循“要指定扩展长度路径,请使用"\\?\" prefix" 推荐,然后使用 Unicode 版本的 API 调用,例如创建文件W https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx, openL不会遇到此类问题。

在该函数的 ANSI 版本中,名称限制为MAX_PATH人物。要将此限制扩展到 32,767 个宽字符,请调用该函数的 Unicode 版本并在前面添加"\\?\"到路径。有关更多信息,请参阅命名文件、路径和命名空间 https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx.

您如何验证文件是否已正确创建?

另请参阅“为什么 Perl 系统调用无法调用内部 Windows 命令? https://stackoverflow.com/questions/10119108/why-is-perl-system-call-failing-to-invoke-internal-windows-command/10122803#10122803” 的解释qx{cmd /c rd /s /q test} https://stackoverflow.com/questions/10119108/why-is-perl-system-call-failing-to-invoke-internal-windows-command/10122803#10122803

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Windows 上使用 Perl 在名称长度超过 220 个字符的目录中创建文件 的相关文章

  • windows bat 文件中的 bang 字符是什么意思?

    我正在尝试更正一个使用 bang 字符的 bat 文件 我本来期望某种形式的引用 就像是 set some var some var 然后后来 some command some var 看起来第一个是在禁用回显的情况下提示输入 例如提示输
  • 生成唯一硬件 ID 的可靠方法

    问题 我必须为每个联网客户端提供唯一的 ID 例如 一旦客户端软件安装在目标计算机上 它 ID 应该持续存在 并且如果在同一台计算机和相同的操作系统安装上重新安装软件 它应该继续存在 如果以大多数方式修改硬件配置 除了更改主板 它不应该改变
  • 尝试从 Polar H10 获取心率变异性 [蓝牙低功耗示例 UWP]

    我正在与 Polar H10 合作 从中获取心率变异性 我在跑步蓝牙低功耗示例 https github com Microsoft Windows universal samples tree master Samples Bluetoo
  • Windows/C++:是否可以找到抛出具有“异常偏移”的异常的代码行

    我们的一位用户在我们的产品启动时遇到异常 她从 Windows 向我们发送了以下错误消息 Problem Event Name APPCRASH Application Name program exe Application Versio
  • VC++ 中的 getopt()

    我非常喜欢使用 GNUgetopt http www gnu org software libtool manual libc Getopt html 当在Linux 据我所知 getopt 在 MS VC 下不可用 Note Win32环
  • 我需要为我的应用程序制作和加载多大尺寸的 ImageList 图标(考虑更高的 DPI)?

    我有一个CListCtrl http msdn microsoft com en us library hfshke78 aspx控制 或ListView http msdn microsoft com en us library wind
  • 动态获取当前LDAP路径

    我正在使用 C 和 NET Framework 4 0 开发一个库 我想检索所有活动目录用户 它效果很好 但我的问题是 如果我在另一个域上运行我的程序 我必须更改此设置 private static string ldapPath LDAP
  • 在 Windows 上使用 PHP 进行分叉/线程的最佳方法是什么?

    我有一个 php 脚本 用于检查许多 数千个 网站上的更新 有时 随着站点数量的增加 情况会更频繁 我在更新其中一个站点时会遇到执行超时 整个脚本都会付诸东流 我能想到的最好的想法是分叉每个更新 所以如果它死了 整体更新就会继续 从我收集到
  • XP 和 Vista 之间使用 Winsock API 的 UDP 多播差异

    Windows XP 和 Windows Vista 之间设置 UDP 多播套接字所需的实现似乎有所不同 具体来说 在 Windows XP 下 您must call bind 在您可以引用任何特定于多播的套接字选项之前 然而 在windo
  • Windows Unicode C++ 流输出失败

    我目前正在编写一个应用程序 它要求我在任意窗口上调用 GetWindowText 并将该数据存储到文件中以供以后处理 长话短说 我注意到我的工具在 战地 3 上失败了 我将问题范围缩小到窗口标题中的以下字符 http www filefor
  • 如何在 Powershell 中为特定命令设置别名?

    有一个命令我经常输入 java jar foo param1 param2 param n 如何创建命令别名来运行此命令 如下所示 launch foo param3 where launch foo被翻译成完整的命令 你必须创建一个函数
  • 如何从 Emacs 中运行 Cygwin Bash Shell?

    我在 Windows 上运行 GNU Emacs 因此输入 M x shell 启动 Windows 命令行 DOS shell 但是 我希望能够从 Emacs 中运行 Cygwin Bash Shell 或任何其他非 Windows sh
  • shell进程的并行执行

    有没有一个工具可以在 Windows 批处理文件中并行执行多个进程 我发现了一些有趣的 Linux 工具 parallel http mi eng cam ac uk er258 code parallel html and PPSS ht
  • 安装 confluence-kafka 时“文件名或扩展名太长”?

    我在使用 pip install confluence kafka 安装 confluence kafka 时遇到一些问题 但我收到此错误 文件名或扩展名太长 详细信息如下 Collecting confluent kafka Using
  • 如何检测媒体是否已插入可移动驱动器/读卡器

    我有一个读卡器 未插入记忆棒 当我插入计算机时 它在 我的电脑 中显示一个空驱动器 是否有可能知道驱动器是否有媒体 抱歉我不知道如何称呼它 或没有 我找到的建议MSalters to use IOCTL STORAGE CHECK VERI
  • 如何在 Intellij IDEA 中为 Apache Tomcat 指定自定义 JRE 路径?

    问题是如何指定自定义JRE路径为Apache tomcat in Intellij IDEA 当从以下位置启动应用程序时IDEA 看来 只需配置它的路径 路径jvm dll in Apache Tomcat监视器没有帮助 还有其他想法或方法
  • 无法加载 php_curl

    我已经在WindowsXp上安装了php5 2 13 apache2 2 15 将C php添加到PATH ssystem变量中 我无法启用卷曲扩展 我配置了extension dir并删除了 在 php ini 中形成 php curl
  • Perl 命令或模块,如 Linux“文件”命令

    我有一个下载文件的脚本 但这些文件在下载之前没有任何有关它们的信息 在为 Linux 编写代码时 我刚刚调用了qx file filename 查看它是否是 JPEG 图像 如果不是则将其删除 然而 我现在正尝试重写为独立于平台的纯 Per
  • Windows 终端中的图标和背景图像字段无法识别父进程目录

    Windows 终端版本 1 12 10732 0 Windows 内部版本号 19043 1645 Issue 如果这个问题已经在其他地方得到解决 请原谅我 但我意识到当Use parent process directory被检查 Co
  • Python 原始字符串和尾随反斜杠[重复]

    这个问题在这里已经有答案了 我曾经遇到过一些东西 想知道它是否是一个 Python bug 或者至少是一个错误功能 我很好奇是否有人知道这种行为的任何理由 我刚刚在阅读 Code Like a Pythonista 时想到了这一点 到目前为

随机推荐

  • 如何用 C 语言为 PIC24 编写与硬件无关的函数

    我正在编写一些实现各种功能的代码 例如 PID 控制器 信号发生器等 我的硬件提供各种输入和输出 刚才我有大量 SWITCH 语句来确定计算的源和目的地 例如 对于 PID 控制器 每 100ms 有一个开关命令 决定将哪个输入传递给 pi
  • 如何通过 PHP 发布到 Google Plus? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想知道是否已经有一个浮动的非官方 PHP 库或类 我可以使用它来发布到用户的 Google Plus
  • 如果不存在则删除表空间

    我已经编写了 pl sql 脚本 可以工作 但看起来不太好 DECLARE v exists NUMBER BEGIN SELECT count INTO v exists FROM dba tablespaces WHERE tables
  • 将结果集从 SQL 数组转换为字符串数组

    我正在查询information schema columns我的 PostgreSQL 数据库中的表 使用表名 结果集查找所有列名 类型以及是否可为空 主键 id 除外 这是正在使用的查询 SELECT column name is nu
  • C# Lambda 表达式:为什么应该使用它们?

    我很快读完了微软 Lambda 表达式 http msdn microsoft com en us library bb397687 aspx文档 不过 这种例子帮助我更好地理解 delegate int del int i del myD
  • Isabelle 返回数字而不是 Suc(Suc( ... 0 ))

    当我使用value为了找出返回自然数的函数的某个值 我总是以 0 的迭代后继函数的形式获得答案 即Suc Suc 0 有时可能很难阅读 有没有办法直接输出Isabelle返回的数字 这是我不久前想修复的问题 但显然我忘记了 卡西吉奈特的猜测
  • 如何从 C# 获取进程窗口类名?

    如何获取某个进程的窗口类名 我想在c 中实现这一点 我已经尝试过 c 中的进程类 但我只能获取进程的窗口名称 Thanks 我假设你的意思是你想获得的类名主窗口一个过程的 为此 您需要使用以下命令获取主窗口的句柄MainWindowHand
  • C中的函数调用[重复]

    这个问题在这里已经有答案了 可能的重复 为什么 gcc 允许将参数传递给定义为不带参数的函数 https stackoverflow com questions 12643202 why does gcc allow arguments t
  • SLURM:如何在同一计算节点或不同节点上并行运行不同的可执行文件?

    Goal 了解如何通过 sbatch 作业提交来运行 共同调度或执行可执行文件 应用程序 使用 srun 或 mpirun 研究 代码片段 bin bash SBATCH job name LEBT SBATCH partition ang
  • Office 脚本(Excel 网页版)获取错误

    我正在尝试从 Web 上的 Excel 调用外部 API 但是 我一直试图从 fetch 调用中获取结果 我什至使用 Office 文档示例来确保 在 Excel 中 单击自动化以创建新脚本 async function main work
  • 按具有不同Where条件的两个字段对数据表进行分组和求和

    我有一个包含示例数据的数据表 如下所示 UserName IsBillable Hours user1 Yes 10 user2 Yes 15 user3 No 20 user1 Yes 25 user1 No 15 user2 Yes 1
  • 如何在不改变纵横比的情况下适应QGraphicsView/QGraphicsScene中的像素图查看

    我正在使用 QGraphicsView QGraphicsScene 来显示图像 图像始终以其原始大小显示 并在末端带有滚动条 我希望 QGraphicsView 根据窗口的大小自动适应图像 保持纵横比 我尝试了这个 但什么也没发生 ui
  • PHP 表单令牌的使用和处理

    我是一个用 PHP 编写登录脚本的初学者 这是我到目前为止所拥有的表单令牌声明 SESSION form token md5 rand time true 该语句是在用户表示他 她想要登录后立即发出的 我有限的理解是 令牌的目的是在唯一的时
  • 取消的 AsyncTask 挂起新的 HttpRequest

    我遇到了 asynctasks 和 http 请求的问题 用户可以按下两个不同的按钮 这两个按钮都从网络服务器下载信息 我希望这些请求可以取消 每次调用之前都会显示一个进度对话框 http请求是在异步任务中执行的 并且我在进度对话框上有一个
  • 在 PHP 中到处使用准备好的语句? (原产地保护)

    我将把在多个站点 项目中使用的数据库类从使用自定义 mysql query 方法 切换到使用 PDO 和准备好的语句 不过我首先有一个问题 我想使用准备好的语句吗到处 即使在查询只运行一次的地方 我需要做类似以下事情的情况该怎么办 INSE
  • Lucene 的 Ruby 替代品

    我经常听说 Lucene 它是 Java 中最好的搜索引擎库之一 Ruby 有类似 同样强大 的库吗 嗯 有Ferret http ferret davebalmain com trac 这是 Lucene 到 Ruby 的端口 此外 Lu
  • Docker:无法打开从容器到主机的端口

    我在用着Docker for Mac 我有一个运行服务器的容器 例如我的服务器在端口 5000 上运行 我已将此端口公开Dockerfile 当我的容器运行时 我连接到该容器并通过运行下面的命令来检查该服务器是否正在工作 并查看它是否返回数
  • 控制试用订阅的访问

    我的任务是建立一个系统 允许我们公司的某人发送一封电子邮件 其中包含一个 pdf 文件的链接 该文件将保存在我们的网络服务器上 收件人可以点击链接查看我们通常销售的新闻通讯 我们的想法是我们这样做三个月 然后看看他们是否愿意继续并支付完整订
  • 如何将带波形符的相对路径渲染为 jquery/javascript 中相对路径的 ../../ ?

    好吧 我知道我的标题有点令人困惑 下面我就用例子来说明清楚
  • 在 Windows 上使用 Perl 在名称长度超过 220 个字符的目录中创建文件

    我遇到一个问题 无法在名称长度超过 220 个字符的目录下创建文件 以下是一个测试脚本 至少在我的机器上重现了观察到的行为 use warnings use strict use Win32 LongPath print system rm