在Windows上使用文件名回车处理文件

时间:2014-02-05 08:23:48

标签: c++ c windows file boost

我有一个外部USB,NTFS格式的硬盘,其中包含许多文件,我最终需要将这些文件复制到Windows Server 2008 R2计算机上的驱动器中。

驱动器上的文件由安装在Solaris上的驱动器运行的脚本放置在那里。执行此副本的用户不小心并在Windows计算机上编辑了他们的副本脚本,从而产生了以下shell脚本行:

cp /sourceDir/sourceFileName /externalDrivePath/targetFileName\r\n

因此,外部驱动器上的文件在其文件名中有一个尾随回车符。标准Windows复制实用程序(copy,xcopy,robocopy)无法复制这些文件,错误为0x7B / 123:“文件名,目录名称或卷标语法不正确。”

我已经测试过了,并且相当确定如果我将驱动器再次安装在Linux机器上,我应该可以使用以下命令修复文件:

mv /externalDrive/targetFileName\r /externalDrivePath/targetFileName\n

但是,我无法立即访问Linux计算机。

到目前为止,我已经尝试过修复/移动这些文件:

Windows Server 2008 R2上的“应用程序”解决方案:

  1. 在Windows资源管理器中重命名文件 - 由于文件数量庞大,这将是不可行的解决方案,但它无论如何都无法正常工作。
  2. 与cmd提示符中的文件名匹配的通配符模式,例如copy E:\externalDrivePath\targetFileName* anotherPath。失败,出现0x7B错误。
  3. 使用8.3(短)文件名从cmd提示符复制文件。根据{{​​1}}
  4. 的输出,有问题的文件没有短名称

    Windows Server 2008 R2上的“编程”解决方案:

    1. 使用Python / Java复制/重命名文件:任何打开/复制回车文件的尝试都会将异常跟踪返回到相同的0x7B Windows错误。
    2. 使用Windows C'CopyFile'API复制文件:失败,出现0x7B错误。在这里,我使用FindNextFile API找到了这些文件,并将该源路径传递给了CopyFile,但操作系统仍无法复制该文件。
    3. 使用fopen,ofstream等在C语言中编写我自己的文件复制功能.fopen调用再次因0x7B而失败。
    4. 使用C ++ boost :: filesystem API复制文件:失败,出现0x7B错误。再次,使用boost :: filesystem :: directory_iterator找到文件并将找到的文件路径传递给boost :: filesystem :: copy_file()
    5. 提供Win32 API CopyFile / MoveFile的文件路径为“\?\ E:\ externalDrivePath \ targetFileName \ r \ n”。调用再次失败,出现0x7B错误。
    6. 我还涉及在OS X机器上安装此驱动器以运行副本,期望它将像Solaris那样为NTFS驱动器提供支持。但是,它无法将类似的错误消息复制到Windows - 我猜OS X的NTFS实现更像“Windows-like”?

      如果这在Windows上是可解的,我觉得它要么需要一个非常低级的C函数来操作FILE本身,而不是根据它的字符串文件名“打开”它。不知道该怎么做。那个,或者我不知道哪些文件修复工具已经包含了这个功能。

      如何实现我所描述的内容的任何替代方法或建议都将非常受欢迎。

2 个答案:

答案 0 :(得分:1)

TLDR:尝试使用前缀为CreateFileW且包含尾随回车符的unicode路径\\?\

\\?\路径语法绕过了许多常用的验证规则,unicode扩展等,并允许长文件路径,甚至(危险地)允许文件名中的斜杠等字符。

考虑到这一点,我想象回车应该是相当微不足道的......

This page relating to long filenames有更多详情。相关部分引用如下

  

不需要对路径和文件名字符串执行任何Unicode规范化以供Windows文件I / O API函数使用,因为文件系统将路径和文件名视为不透明的WCHAR序列。在对相关Windows文件I / O API函数进行任何调用之外,应记住应用程序所需的任何规范化。

     

使用API​​创建目录时,指定的路径不能太长,以至于无法附加8.3文件名(即目录名不能超过MAX_PATH减去12)。   shell和文件系统有不同的要求。 可以使用Windows API创建一个shell用户界面无法正确解释的路径。

来自here

  

在较新的文件系统(例如NTFS,ex-FAT,UDFS和FAT32)上,Windows以Unicode格式将长文件名存储在磁盘上,这意味着始终保留原始长文件名。即使长文件名包含扩展字符,也不管在磁盘读取或写入操作期间处于活动状态的代码页,都是如此。即使文件系统不区分大小写,也会保留文件名的大小写......

答案 1 :(得分:0)

我在90年代中期在Windows 3.11上遇到了类似的问题。

我最终使用了来自C程序的rename(在<stdio.h>中声明)。

如果失败,您可以尝试低级C系统调用:openreadwrite将文件复制到新名称。

低级别通话通常会绕过用户友好的高级功能所施加的限制。