[Perl] Windows 系统 Unicode 文件名操作(新建、重命名、枚举、复制)全攻略

环境 XP/WIN7 Perl v5.16

编辑整理:PerlMonk、523066680

常见的那些文件操作函数都不支持,于是为了达到目的,需要各种方法配合,应该是不如其他语言方便。

我只是想看看Perl到底是否适合做这件事,于是折腾了一回。

文件的建立:

模块:Win32
Code: [全选] [展开/收缩] [Download] (example.pl)
use Win32;
use utf8;
use Encode; #接受unicode传参
Win32::CreateFile("W32CreateFile・测试");
特性: 成功返回true,但不返回文件句柄
Creates the FILE and returns a true value on success.
Check $^E on failure for extended error information. 模块:Win32API::File
函数:$hObject= CreateFileW( $swPath, $uAccess, $uShare, $pSecAttr, $uCreate, $uFlags, $hModel )
$hObject可以返回文件对象句柄
注意事项: 传入的文件路径的编码格式为:UTF16-LE ,必须以\x00结尾,示例(代码保存为utf8格式):
Code: [全选] [展开/收缩] [Download] (example.pl)
use Win32API::File qw(:ALL);
use utf8;
use Encode;
$str="文tes・t.txt\x00";
$hobject=CreateFileW(encode('UTF16-LE', $str), GENERIC_WRITE, 0, [], OPEN_ALWAYS,0,0);

目录的建立

模块:Win32
Code: [全选] [展开/收缩] [Download] (example.pl)
use Win32;
use utf8; Win32::CreateDirectory("Dir・测试");

文件的枚举

在遇到unicode字符的时候,File::Find模块 以及 IO::Dir 模块都只能输出文件短名。
暂时用CMD /U Dir 的方法输出文件列表(郁闷吧,暂时没找到能完美操作的内置模块)
参考文章
http://www.perlmonks.org/?node_id=536223
how to read unicode filename

复制某个文件夹内的文件(文件名含unicode字符)

模块:Win32API::File
如果先获取文件的短名,然后再复制,但是目标文件名也会变成短名。
于是暂时用cmd /U 模式获取文件列表,然后CopyFileW进行复制:
Code: [全选] [展开/收缩] [Download] (example.pl)
use Win32API::File qw':ALL';
use Encode;
use utf8; my $src=encode('gbk','.\\测试目录');
my $dst='.\\Target'; #该目录只有一层,/s开关是为了列出完整的路径
my $all=`cmd /U /C dir /s /b \"$src\"`;
my $fn; foreach (split(/\x0d\x00\x0a\x00/, $all)) {
$fn = encode('gbk', decode('utf16-le',$_))."\n";
@xrr=split(/\x5c\x00/, $_);
CopyFileW(
$_ ."\x00",
encode('utf-16le', decode('utf8', "$dst\\")).$xrr[$#xrr]."\x00",
1
);
print "$^E\n" if ($^E);
}
<STDIN>;
细节一、
正确地使用 split $all 截断utf-16le字符段落,分隔符为0d 00 0a 00
参考枚举脚本 细节二、
如果用basename()分割路径,同样会遇到00被忽略的问题,'\\' 的U16LE
编码是5C 00,但是basename 只按5C截断,剩下的00造成了处理乱码。 测试basename的第二个参数设置为 "\x5c\x00" 并不能解决这个问题
解决方法一、
手工去掉开头处00
方法二、
先转为GBK,再获取basename,再转utf-16le
2014-12-12 备注这种方法在LongPath的情况下,会丢失unicode字符
可以考虑转为UTF-8,不管怎么说都有点绕
方法三、
自己用正则表达式获取
/\x5C\x00([^\x5c]+)$/;
$1
方法四、
@xrr=split(/\x5c\x00/, $_);
$xrr[$#xrr] 细节三、
CopyFileW复制文件时,要在末尾加\x00作为字符串终止符
否则各种问题=_=

判断文件是否存在:

方法一:先转为短名再判断,不做赘述
方法二:渣方法,用CreateFileW测试建立同名文件,看是否有冲突

重命名:

模块:Win32API::File
Code: [全选] [展开/收缩] [Download] (example.pl)
MoveFileW(
encode('utf-16le', decode('utf8',$F))."\x00",
encode('utf-16le', decode('utf8',$newname))."\x00"
);

获取文件的日期信息:

普通文件名的情况
http://stackoverflow.com/questions/1839877/
how-can-i-get-a-files-modification-date-in-ddmmyy-format-in-perl 含有Unicode字符的文件名的情况
http://www.perlmonks.org/?node_id=741797
How to stat a file with a Unicode (UTF16-LE) filename in Windows?
其中的方法是通过createfileW 获取文件句柄,然后用OsFHandleOpen获取通用的文件句柄对象,并传入state
(感觉特别绕) 另一种就是先转为短名再获取日期,但是这种方法在处理文件量大的时候,效率非常低。前面perlmonks中的方法
效率要高得多
Code: [全选] [展开/收缩] [Download] (example.pl)
use utf8;
use Encode;
use Win32; $filename='D:\测试目录\董贞 ・ 01.剑如虹.[贞江湖].mp3';
$filename=Win32::GetShortPathName($filename); my $mtime = (stat $filename)[9];
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($mtime);
$year+=1900;
$mon+=1;
print "$year-$mon-$mday\n";
<STDIN>;

=补充=====

tigerpower 推荐了 Win32::Unicode

我以前执着于用自带的模块做文件系统的事情,现在想想真没必要,应该怎么方便怎么来。

这里重新补充

http://bbs.bathome.net/redirect.php?goto=findpost&ptid=34881&pid=168889&fromuid=3337

代码: 全选

use Win32::Unicode;

use utf8;

my $dirname="CreateDir・测试";

my $dirname_long="CreateDir・测试1/CreateDir・测试2/CreateDir・测试3";

my $dirname_new="CreateDir・测试・新";

my $filename="CreateFile・测试";

mkdirW $dirname;

chdirW $dirname;

mkpathW $dirname_long;

$fh = Win32::Unicode::File->new('>', $filename);

$fh->close;

chdirW $dirname_long;

touchW $filename.'1';

chdirW '../../../..';

cptreeW $dirname.'/',$dirname_new;

[Perl]Windows 系统 Unicode 文件名操作(新建、重命名、枚举、复制)全攻略的更多相关文章

  1. Windows 系统 Unicode 文件名操作(新建、重命名、枚举、复制)全攻略

    常见的那些文件操作函数都不支持,于是为了达到目的,需要各种方法配合,应该是不如其他语言方便.我只是想看看Perl到底是否适合做这件事,于是折腾了一回. 文件的建立: 模块:Win32 Code: [全 ...

  2. delphi 文件的操作:重命名、复制、移动、删除

    Delphi 文件的操作:重命名.复制.移动.删除第一种方法: RenameFile('Oldname', 'Newname'); CopyFile(PChar('Oldname'), PChar(' ...

  3. linux下的文件操作——批量重命名

    概述:在日常工作中,我们经常需要对一批文件进行重命名操作,例如将所有的jpg文件改成bnp,将名字中的1改成one,等等.文本主要为你讲解如何实现这些操作 1.删除所有的 .bak 后缀: renam ...

  4. Windows系统,文件和文件夹命名规则:

    不能包含:< > / \ | : * ? windows中,文件名(包括扩展名)可高达 个字符.文件名可以包含除 ? “ ”/ \ < > * | : 之外的大多数字符:保留文 ...

  5. 【转】Perl Unicode全攻略

    Perl Unicode全攻略 耐心看完本文,相信你今后在unicode处理上不会再有什么问题. 本文内容适用于perl 5.8及其以上版本. perl internal form 在Perl看来, ...

  6. Perl Unicode全攻略

    Perl Unicode全攻略 耐心看完本文,相信你今后在unicode处理上不会再有什么问题. 本文内容适用于perl 5.8及其以上版本. perl internal form 在Perl看来, ...

  7. 2.3《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——重命名,复制,删除

    最常用的文件操作除了将文件列出来外,就应该是重命名,复制,删除了.正如将文件列出来一样,大多数现代操作系统为这些任务提供了用户图形界面,但是在许多场景中,用命令行还是会更方便. 使用mv命令重命名一个 ...

  8. linux 下文件重命名/移动/复制命令(转)

    linux 下文件重命名/移动/复制命令(转) linux下重命名文件:使用mv命令就可以了, 例:要把名为:abc   重命名为:123 可以这样操作: 重命名:MV命令 1.进入你的文件目录,运行 ...

  9. Windows Socket五种I/O模型——代码全攻略(转)

    Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模式.可以通过多线程技术进行处理. 非阻塞模式:执行I/O操 ...

随机推荐

  1. Core 第三组 结对作业——四则运算 Part1. Core代码编写

    结对作业——四则运算 Part1. Core代码编写 PB15061303 刘梓轩PB16061489 艾寅中 GITHUB 地址 戳这里 目录 (因为内容较多,分为了三个部分,但作业系统中只能提交一 ...

  2. Apache Flume的介绍安装及简单案例

    概述 Flume 是 一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的软件.Flume 的核心是把数据从数据源(source)收集过来,再将收集到的数据送到指定的目的地(sink).为了保证 ...

  3. markdown转HTML,目录生成

    1.首先,准备好已经编辑好的markdown文件放到指定目录下. 2.下载node.js,下载地址:https://nodejs.org/en/download/ 3.下载好node.js文件后,配置 ...

  4. 服务器安装Ubuntu的那些坑

    1. 虽然简体中文很亲切,但请选择English,否则极有可能安装途中报错 2. 安装完各种系统文件后,请注意选择启动Disk,一不小心跳过了貌似只好重装 3. 进入后无法使用apt-get,总提示需 ...

  5. DNS处理模块dnspython

    一.介绍 官网:http://www.dnspython.org/ https://pypi.org/project/dnspython/ dnspython是Python的DNS工具包.它支持几乎所 ...

  6. 17-list,字典使用练习

    randint(a,b)包括 [a,b]中随机, 包含a,b range(n)= 0,1,2,3....n-1 chr() 数字转字符: chr(65) 得到 :A ord()字符转数字:  ord( ...

  7. JMS 之 Active MQ的安全机制

    一.认证 认证(Authentication):验证某个实体或者用户是否有权限访问受保护资源. MQ提供两种插件用于权限认证:(一).Simple authentication plug-in:直接把 ...

  8. eclipse查看jar包中的class文件出现乱码

    参考:http://blog.csdn.net/bell2008/article/details/40978959 1,问题来源是在eclipse中直接查看springside的class(由ecli ...

  9. idea 启动报错问题

    Artifact SpiderServer:war exploded: Error during artifact deployment. See server log for details. 1. ...

  10. mybatis insert 自动生成key

    <selectKey keyProperty="id" resultType="java.lang.String" order="BEFORE& ...