我使用File::Find
遍历目录树和Win32::File
的{{1}}函数来查看其中找到的文件的属性。这适用于单线程程序。
然后我将目录遍历移动到一个单独的线程中,它停止工作。 GetAttributes
在GetAttributes
中出现错误消息“{系统无法找到指定的文件”的每个文件都失败。
我将问题追溯到$^E
使用File::Find
的事实,显然chdir
不使用当前目录。我可以通过传递一个绝对路径来解决这个问题,但是后来我可能会遇到路径长度限制,并且在这个脚本运行的地方肯定会出现长路径,所以我真的需要利用GetAttributes
和相对路径。
为了演示这个问题,这里有一个脚本,它在当前目录中创建一个文件,在子目录中创建另一个文件,在子目录中创建chdir,并以3种方式查找文件:chdir
,{{1} }和system("dir")
。
当脚本在没有参数的情况下运行时,open
显示子目录,GetAttributes
在子目录中找到该文件,dir
成功返回其属性。使用open
运行时,所有测试都在子线程中完成,GetAttributes
和--thread
仍然有效,但dir
失败。然后它调用原始目录中的文件open
(我们有chdir'ed),然后找到一个!不知怎的GetAttributes
正在使用进程的原始工作目录 - 或者可能是主线程的工作目录 - 与所有其他文件操作不同。
我该如何解决这个问题?如果重要的话,我可以保证主线程不会做任何chdir'ing。
GetAttributes
答案 0 :(得分:0)
最后,我发现perl正在维护某种仅适用于perl内置运算符的辅助cwd,而GetAttributes
正在使用本机cwd。我不知道为什么会这样做或为什么它只发生在辅助线程中;我最好的猜测是perl试图模仿每个进程一个cwd的unix规则,并因为Win32::*
模块不能正常运行而失败。
无论是什么原因,只要您正在进行Win32::*
操作,就可以通过强制原生cwd与perl的cwd相同来解决问题,像这样:
use Cwd;
use Win32::FindFile qw/SetCurrentDirectory/;
...
SetCurrentDirectory(getcwd());
可以说,File::Find
在Win32上运行时应该这样做。
当然这只会使"路径名太长"更糟糕的是,因为现在你访问的每个目录都是绝对路径SetCurrentDirectory
的目标;试着用一系列较小的SetCurrentDirectory
电话来解决这个问题,你必须找到一种方法来回到你来自哪里,当你甚至没有fchdir
时这很难。