[Perl]Windows 系统 Unicode 文件名操作(新建、重命名、枚举、复制)全攻略
[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 文件名操作(新建、重命名、枚举、复制)全攻略的更多相关文章
- Windows 系统 Unicode 文件名操作(新建、重命名、枚举、复制)全攻略
常见的那些文件操作函数都不支持,于是为了达到目的,需要各种方法配合,应该是不如其他语言方便.我只是想看看Perl到底是否适合做这件事,于是折腾了一回. 文件的建立: 模块:Win32 Code: [全 ...
- delphi 文件的操作:重命名、复制、移动、删除
Delphi 文件的操作:重命名.复制.移动.删除第一种方法: RenameFile('Oldname', 'Newname'); CopyFile(PChar('Oldname'), PChar(' ...
- linux下的文件操作——批量重命名
概述:在日常工作中,我们经常需要对一批文件进行重命名操作,例如将所有的jpg文件改成bnp,将名字中的1改成one,等等.文本主要为你讲解如何实现这些操作 1.删除所有的 .bak 后缀: renam ...
- Windows系统,文件和文件夹命名规则:
不能包含:< > / \ | : * ? windows中,文件名(包括扩展名)可高达 个字符.文件名可以包含除 ? “ ”/ \ < > * | : 之外的大多数字符:保留文 ...
- 【转】Perl Unicode全攻略
Perl Unicode全攻略 耐心看完本文,相信你今后在unicode处理上不会再有什么问题. 本文内容适用于perl 5.8及其以上版本. perl internal form 在Perl看来, ...
- Perl Unicode全攻略
Perl Unicode全攻略 耐心看完本文,相信你今后在unicode处理上不会再有什么问题. 本文内容适用于perl 5.8及其以上版本. perl internal form 在Perl看来, ...
- 2.3《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——重命名,复制,删除
最常用的文件操作除了将文件列出来外,就应该是重命名,复制,删除了.正如将文件列出来一样,大多数现代操作系统为这些任务提供了用户图形界面,但是在许多场景中,用命令行还是会更方便. 使用mv命令重命名一个 ...
- linux 下文件重命名/移动/复制命令(转)
linux 下文件重命名/移动/复制命令(转) linux下重命名文件:使用mv命令就可以了, 例:要把名为:abc 重命名为:123 可以这样操作: 重命名:MV命令 1.进入你的文件目录,运行 ...
- Windows Socket五种I/O模型——代码全攻略(转)
Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模式.可以通过多线程技术进行处理. 非阻塞模式:执行I/O操 ...
随机推荐
- iOS学习之WebView的使用
1.使用UIWebView加载网页 运行XCode 4.3,新建一个Single View Application,命名为WebViewDemo. 2.加载WebView 在ViewControlle ...
- [JS] 让人犯晕的JavaScript变量赋值
变量赋值 本文转载自http://hellobug.github.io/blog/javascript-variable-assignment/ 开始之前先来几个例子,确保起始点是晕的状态- :P 例 ...
- Git Hook 同步服务器代码
参考并转载自: http://www.embbnux.com/2014/09/05/git_server_let_code_auto_deploy/ http://www.chenyudong.com ...
- Hello Build To Win!我们是奶牛小分队!——记第一次团队作业
Hello Build To Win!我们是奶牛小分队! section 1 组建团队 1. 队员介绍: 姓名 学号 风格 擅长技术 编程兴趣 希望软工角色 吴建瑜 2016012024 努力学习, ...
- Java CST格式字符串转换成Date类型的数据
Date date = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US).parse("We ...
- Centos7.2下编译安装python3.7
1.安装python3.7所需要的依赖. yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel rea ...
- Spring Data Solr操作solr的简单案例
Spring Data Solr简介 虽然支持任何编程语言的能力具有很大的市场价值,你可能感兴趣的问题是:我如何将Solr的应用集成到Spring中?可以,Spring Data Solr就是为了方便 ...
- Nginx 源码完全注释(11)ngx_spinlock
Nginx 是多进程模式的,一个 master 与多个 workers,一般工作在多核 CPU 上,所以自旋锁就是必须用到的.Nginx 中的自旋锁的定义,位于 ngx_spinlock.c 中,如下 ...
- java-tip-HashMap
HashMap的基本查找过程: 先使用key.hashCode()生成哈希值,根据哈希值来确定key存放的位置 找到key在数组中的位置后,再使用key.equals()方法来找到指定的key. 1. ...
- Cloudstack4.2之改变数据卷容量的大小(Resize Data Volumes)
下图标注了这个功能在cloudstack4.2 UI中的位置 在cloudstack中是通过磁盘服务来设定卷的大小的.管理员可以设置相应的磁盘服务以供用户来使用.为了增强系统的灵活性,方便最终用户的使 ...