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)
11
  • This answer may help Commented Nov 6, 2014 at 19:43
  • what are your paths? link_dst, link_src Commented Nov 6, 2014 at 19:47
  • @Andy I had tried that and I get Undefined Variable From Import: CreateSymbolicLinkW Commented Nov 6, 2014 at 19:48
  • @User 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" Commented Nov 6, 2014 at 19:51
  • 1
    If you can use Python 3 it's simply os.symlink. Commented Dec 7, 2014 at 8:21

3 Answers 3

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
Sign up to request clarification or add additional context in comments.

4 Comments

Ok, I changed the policy so that myself as normal user can create symlinks, But it does not seem to work.
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?
No, File Not Found instead. This is because "r" does not exist before the paths in my script right?
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.
5

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

Comments

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.