如何使用Perl创建符号链接?

4

我正在尝试在Perl中运行以下代码:

symlink($oldname,$newname) or die print "$!\n";

但是我收到了一个错误提示:
The symlink function is unimplemented at C:\...\CreateSymlink.pl line 14.

如果我将代码更改为:

link($oldname,$newname) or die print "$!\n";

然后,硬链接被创建时没有出现错误。

使用ActiveState Perl和Windows 7 32位。

为什么会发生这种情况?我正在尝试为一个文件创建符号链接。

P.S:我是Perl的新手。


4
在谷歌上搜索“windows symlink perl”会返回大量关于此的信息。简短的答案是,在Windows中没有像*nix中那样的“symlink”。Perl文档告诉您,如果底层操作系统不支持符号链接,则symlink将失败。 - Brian Roach
1
@Brian Roach 当然有啦...嗯,在过去5年中发布的Windows版本中就有了;-) - user166390
2
@pst - 这在 Perl 中不可用;它是一个系统命令。再加上需要以提升的权限运行才能创建 NTFS 符号链接,我会坚持认为“不一样”。 - Brian Roach
1
@BrianRoach,至少可以创建Junctions(目录符号链接)而无需提升权限。 - antred
@BrianRoach 在NTFS中有真正的符号链接。作为符号链接,它们是相同的。实现取决于文件系统,而不是操作系统。如果在Windows中符号链接管理具有不同的使用限制,那就是完全无关的事情。Perl应该像在*nix文件系统中一样创建、测试和读取NTFS中的符号链接。它们的工作方式相同,只是在实现方式上有所不同。但是,Perl开发人员迄今为止并没有关心Win32中当前的可移植性,这源于过去它在Win32中不受支持,也不是Win32中存在的功能。 - Francisco Zarabozo
显示剩余4条评论
2个回答

9

哪种“符号链接”?;-)

哦,阅读上面的符号链接维基百科文章以了解mklink命令;-) 反引号(或系统)可以成为好朋友,但请注意:

Windows Vista/Windows 7中的默认安全设置禁止非提升管理员和所有非管理员创建符号链接。这种行为可以通过[安全策略设置]更改....

编程愉快。


WinAPI的CreateSymbolicLink函数可能可以直接使用;我不确定它是否会像上面的mklink命令一样受到相同的限制。然而,这个线程表明它仍然有效。


就我所知,在草莓Perl 5.12中,这个“可以工作”。你的情况可能有所不同,我只是打了这个代码,从未使用过其他方式:-)

use Win32::API;
$fn = Win32::API->new(
    # Note "A" function, IDK how to use Unicdoe
    "kernel32", "BOOLEAN CreateSymbolicLinkA(LPTSTR lpSymlinkFileName, LPTSTR lpTargetFileName, DWORD flags)"
);

unlink("src.txt");
unlink("lnk.txt");
open(FH,">src.txt") or die $!;
close(FH);

print "src.txt exists? " , (-f "src.txt"), "\n";
print "lnk.txt exists? " , (-f "lnk.txt"), "\n";
$hr = $fn->Call("lnk.txt", "src.txt", 0);
print "Result: ", $hr, "\n";
print "lnk.txt exists? ", (-f "lnk.txt"), "\n";

open(FH,">>src.txt") or die $!;
print FH "hello world!\n";
close(FH);

open(FH,"<lnk.txt") or die $!;
print "linked data: ", scalar(<FH>), "\n";
close(FH);

我的结果(以“管理员”身份运行--可能不适用于“其他用户”--我不知道为什么,但我的cmd.exe总是以提升的权限打开):

src.txt存在吗?1
lnk.txt存在吗?
结果:
lnk.txt存在吗?1
链接数据:hello world!

目录列表:

10/22/2011  02:53 PM    <DIR>          .
10/22/2011  02:53 PM    <DIR>          ..
10/22/2011  02:54 PM               636 foo.pl
10/22/2011  02:53 PM    <SYMLINK>      lnk.txt [src.txt]
10/22/2011  02:53 PM                14 src.txt

我不知道NTFS符号链接和“UNIX”符号链接之间是否存在[微妙]差异。此外,上述内容在Vista / 2008之前不起作用——NTFS的早期版本不支持符号链接(以及Windows的早期版本没有CreateSymbolicLink函数)。


种类:NTFS 符号链接。我已经以管理员身份登录,命令提示符的标题也显示为管理员。如何在 Perl 脚本中运行 mklink? - Red
你的代码运行良好。但是当我尝试将其集成到我的代码中时,什么也没有发生。code使用Win32::API; $fn = Win32::API->new( # 注意 "A" 函数,我不知道如何使用 Unicode "kernel32", "BOOLEAN CreateSymbolicLinkA(LPTSTR lpSymlinkFileName, LPTSTR lpTargetFileName, DWORD flags)" ); $hr = $fn->Call($oldname, $newname, 0); code - Red
@Red "什么都没有发生" 还是 ...? - user166390
我添加了print语句: code $hr = $fn->Call($oldname, $newname, 0) or die print "$!\n"; code,现在在控制台中显示: C:...\CreateSymlink.pl的第20行返回1。 - Red
请注意,Windows 调用通常会返回一个“结果”为 0(似乎被映射为未定义???...无论如何,它是假的)表示“成功”。确保路径(相对/绝对)正确,并记得传递“directory”标志以链接目录。这是一个 Windows 调用,因此它使用 Windows 路径规则。不知道还有什么要说的 :) - user166390

1
制定了一个解决方法:
my $oldfilename = File::Spec->catfile($oldname);
my $newfilename = File::Spec->catfile($newname);
if(-f $newfilename){ } else {
    @args = ("mklink", $newfilename, $oldfilename);
    system(@args) == 0; } 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接