How to create symlinks in windows using Python?
Asked Answered
H

3

5

I am trying to create symlinks using Python on Windows 8. I found This Post and this is part of my script.

import os

link_dst = unicode(os.path.join(style_path, album_path))
link_src = unicode(album_path)
kdll = ctypes.windll.LoadLibrary("kernel32.dll")
kdll.CreateSymbolicLinkW(link_dst, link_src, 1)

Firstly, It can create symlinks only when it is executed through administrator cmd. Why is that happening?

Secondly, When I am trying to open those symlinks from windows explorer I get This Error:

...Directory is not accessible. The Name Of The File Cannot Be Resolved By The System.

Is there a better way of creating symlinks using Python? If not, How can I solve this?

EDIT

This is the for loop in album_linker:

def album_Linker(album_path, album_Genre, album_Style):
genre_basedir = "E:\Music\#02.Genre"
artist_basedir = "E:\Music\#03.Artist"
release_data_basedir = "E:\Music\#04.ReleaseDate"
for genre in os.listdir(genre_basedir):
    genre_path = os.path.join(genre_basedir, "_" + album_Genre)
    if not os.path.isdir(genre_path):
        os.mkdir(genre_path)
    album_Style_list = album_Style.split(', ')
    print album_Style_list
    for style in album_Style_list:
        style_path = os.path.join(genre_path, "_" + style)
        if not os.path.isdir(style_path):
            os.mkdir(style_path)
        album_path_list = album_path.split("_")
        print album_path_list
        #link_dst = unicode(os.path.join(style_path, album_path_list[2] + "_" + album_path_list[1] + "_" + album_path_list[0]))
        link_dst = unicode(os.path.join(style_path, album_path))
        link_src = unicode(album_path)
        kdll = ctypes.windll.LoadLibrary("kernel32.dll")
        kdll.CreateSymbolicLinkW(link_dst, link_src, 1)

It takes album_Genre and album_Style And then It creates directories under E:\Music\#02.Genre . It also takes album_path from the main body of the script. This album_path is the path of directory which i want to create the symlink under E:\Music\#02.Genre\Genre\Style . So album_path is a variable taken from another for loop in the main body of the script

for label in os.listdir(basedir):
label_path = os.path.join(basedir, label)
for album in os.listdir(label_path):
    album_path = os.path.join(label_path, album)
    if not os.path.isdir(album_path):
        # Not A Directory
        continue
    else:
        # Is A Directory
        os.mkdir(os.path.join(album_path + ".copy"))
        # Let Us Count
        j = 1
        z = 0
        # Change Directory
        os.chdir(album_path)
Hunterhunting answered 6/11, 2014 at 19:31 Comment(11)
This answer may helpRalli
what are your paths? link_dst, link_srcArta
@Ralli I had tried that and I get Undefined Variable From Import: CreateSymbolicLinkWHunterhunting
@Arta This Code exists in a for loop. So the paths are changing. As an example link_dst = "E:\Music\#02.Genre_Electronic_Bass Music\1-800Dinosaur-1-800-001_[JamesBlake-Voyeur(Dub)AndHolyGhost]_2013-05-00" and link_dst = "E:\Music\#01.Label_1-800Dinosaur\1-800Dinosaur-1-800-001_[JamesBlake-Voyeur(Dub)AndHolyGhost]_2013-05-00"Hunterhunting
Those paths aren't escaped properly... try link_dst = r"E:\Music...Hyperplasia
@Hyperplasia well each path, is taken from a for loop. As a result, "E:\Music..." is a variable in the script. I know that If I have the path then I should Use this "r" letter before the path ( Even if I do not know exactly what it does :( ). But what if i do not have the path but it is stored in a variable? Can I use r(link_dst) ??Hunterhunting
@gabriel, the "r" tells python not to treat "\" specially. Without "r", "\n" is the newline character. With the "r", r"\n" is two characters, the backslash and the newline. The 'r" only works on assignment, like when you first write the "E:\Music..." variable.Hyperplasia
@Hyperplasia Ok, now I understand why i should use "r" :P. I edited the post to explain that i cannot know the path as a string but only as a variable. As far I understand from what you wrote in the previous comment, I cannot type r(album_path), album_path--> path stored from a for loop. Right? Is there any other way to do this? For example u'E:\Music...' is the same as unicode(album_path) right?Hunterhunting
okay, since you got the strings from os.listdir, you don't need to worry about raw strings or backslash escaping.Hyperplasia
Let us continue this discussion in chat.Hunterhunting
If you can use Python 3 it's simply os.symlink.Circuity
H
10

Firstly, It can create symlinks only when it is executed through administrator cmd.

Users need "Create symbolic links" rights to create a symlink. By default, normal users don't have it but administrator does. One way to change that is with the security policy editor. Open a command prompt as administrator, run secpol.msc and then go to Security Settings\Local Policies\User Rights Assignment\Create symbolic links to make the change.

Secondly, When I am trying to open those symlinks from windows explorer I get This Error:

You aren't escaping the backslashes in the file name. Just by adding an "r" to the front for a raw string, the file name changes. You are setting a non-existant file name and so explorer can't find it.

>>> link_dst1 = "E:\Music\#02.Genre_Electronic_Bass Music\1-800Dinosaur-1-800-001_[JamesBlake-Voyeur(Dub)AndHolyGhost]_2013-05-00"
>>> link_dst2 = r"E:\Music\#02.Genre_Electronic_Bass Music\1-800Dinosaur-1-800-001_[JamesBlake-Voyeur(Dub)AndHolyGhost]_2013-05-00"
>>> link_dst1 == link_dst2
False
>>> print link_dst1
E:\Music\#02.Genre_Electronic_Bass Music☺-800Dinosaur-1-800-001_[JamesBlake-Voyeur(Dub)AndHolyGhost]_2013-05-00
Hyperplasia answered 6/11, 2014 at 19:59 Comment(4)
Ok, I changed the policy so that myself as normal user can create symlinks, But it does not seem to work.Hunterhunting
What does it look like on the command line? Do a dir in the directory with the link, does it look something like 11/06/2014 01:28 PM <SYMLINKD> link_dir [target_dir] and can you cd into it?Hyperplasia
No, File Not Found instead. This is because "r" does not exist before the paths in my script right?Hunterhunting
Not necesarily. It depends on where the string came from. If its a string in your program (common when trying to debug things) you need either the "r" or write backslashes as \\. If you got it from os.listdir, you're okay. How about posting the result of the dir command like I did above. It may give a clue.Hyperplasia
O
5

os.symlink works out of the box since python 3.8 on windows, as long as Developer Mode is turned on.

Opium answered 20/7, 2020 at 18:45 Comment(0)
F
1

If you're just trying to create a link to a directory, you could also create a "Junction", no admin privileges required:

import os
import _winapi

src_dir = "C:/Users/joe/Desktop/my_existing_folder"
dst_dir = "C:/Users/joe/Desktop/generated_link"

src_dir = os.path.normpath(os.path.realpath(src_dir))
dst_dir = os.path.normpath(os.path.realpath(dst_dir))

if not os.path.exists(dst_dir):
   os.makedirs(os.path.dirname(dst_dir), exist_ok=True)
   _winapi.CreateJunction(src_dir, dst_dir)
Footrest answered 5/4, 2022 at 23:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.