How to create symlink using Perl?
Asked Answered
M

2

5

Am trying to run the below code in Perl:

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

but I get an error saying:

The symlink function is unimplemented at C:\...\CreateSymlink.pl line 14.

If I change the code to:

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

then the hard links are being created without errors.

Using activestate Perl and Windows 7 32-bit.

Any ideas why this is happening? I am trying to create symbolic links for a file.

P.S: I am a total newbie to Perl.

Munda answered 22/10, 2011 at 21:6 Comment(9)
googling windows symlink perl returns lots and lots of information about this. The short answer is that there's no such thing as a "symlink" like there is in *nix in windows. The perl docs tell you that if the underlying OS doesn't support symlinks, symlink will fail.Hom
@Brian Roach Sure there is ... well, in windows versions released in the past 5 years ;-)Sportsmanship
@pst - note the words "like there is in *nix". They're ... not the same. You'd think activestate would do something rather than just fail, but they don't.Hom
@Brian Roach Ever use mklink? It's not well know, but has not failed me yet for a "symbolic link"... I'm sure there are subtle differences, but I have not looked into it further. Junction-points are indeed different beasts.Sportsmanship
@pst - that's not available in perl; it's a system command. Add the fact that you need to be running with elevated privileges to create an NTFS symlink and I'm going to stick with "Not the same"Hom
@Brian Roach Ah hah! So it could be implemented with the "restriction" which can be controlled per machine policy... I did update my answer with the restriction, I guess I'm just "always a god" on this box ;-)Sportsmanship
How come NTFS hard link is being created but not the symbolic link? Running same code with the above mentioned difference.Munda
@BrianRoach Junctions (directory symlinks) at least could be created without requiring elevated permissions.Heartburning
@BrianRoach There are true symlinks in NTFS. As symlinks, they are the same. The implementation depends on the file system, not the OS. If symlink management has different restritions of use in Windows, that's a completely unrelated matter. Perl should create, test and read symlinks in NTFS like it does for filesystems in *nix. They work in the same way, they are different just in terms of how they are implemented. But Perl developers just haven't cared so far about the current portability in Win32, coming from a past where it was not supported and just not an existent feature in Win32.Blackdamp
S
11

Which "kind" of "symbolic link"? ;-)

Oh, and read the symbolic link Wikipedia article above for the mklink command ;-) Back-ticks (or system) can be a good friend, but note:

The default security settings in Windows Vista/Windows 7 disallow non-elevated administrators and all non-administrators from creating symbolic links. This behavior can be changed [by a security policy setting]....

Happy coding.


The WinAPI CreateSymbolicLink function might be useable directly; I am not sure if it "suffers" from the same restriction as a mklink command above. However, this thread indicates it is still in effect.


FWIW, this "works" in Strawberry Perl 5.12. YMMV, I just typed this up and have never used it otherwise :-)

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);

My results (ran as "Administrator" -- may not work for "other users" -- I dunno why but my cmd.exe is always opening with elevated privileges):

src.txt exists? 1
lnk.txt exists?
Result:
lnk.txt exists? 1
linked data: hello world!

Directory listing:

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

I have no idea what [subtle] differences there may be, if any, between NTFS symbolic links and "UNIX" symbolic links. Also, the above won't work pre-Vista/2008 -- previous versions of NTFS do not support symbolic links (and previous versions of windows do not have the CreateSymbolicLink function).

Sportsmanship answered 22/10, 2011 at 21:10 Comment(5)
kind: NTFS Symbolic Link. I am logged in as administrator and the cmd prompt does say administrator in its title. how to run mklink in perl script?Munda
Your code works fine. But when i try to integrate inside mine then nothing happens. code use Win32::API; $fn = Win32::API->new( # Note "A" function, IDK how to use Unicdoe "kernel32", "BOOLEAN CreateSymbolicLinkA(LPTSTR lpSymlinkFileName, LPTSTR lpTargetFileName, DWORD flags)" ); $hr = $fn->Call($oldname, $newname, 0); codeMunda
@Munda "nothing happens" or ...?Sportsmanship
I added print: code $hr = $fn->Call($oldname, $newname, 0) or die print "$!\n"; code now getting in console: 1 at C:\...\CreateSymlink.pl line 20.Munda
@Munda Keep in mind that windows calls [usually] return a "result" of 0 (seems to be mapped to undef??? ... in any case it's falsy) on "success". Make sure the paths (relative/absolute) are correct and remember to pass in the "directory" flag to link a directory. It's a windows call so it uses windows pathing rules. Not sure what to say otherwise :)Sportsmanship
M
1

Made a workaround:

my $oldfilename = File::Spec->catfile($oldname);
my $newfilename = File::Spec->catfile($newname);
if(-f $newfilename){ } else {
    @args = ("mklink", $newfilename, $oldfilename);
    system(@args) == 0; } 
Munda answered 24/10, 2011 at 4:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.