简体   繁体   中英

How to create symlink in Python using only relative paths

Consider a simple function to make a directory and then a symlink to the directory, all required to be assumed under the current working directory. In the case when the directory and link are directly within the current working directory, this process succeeds. But when the directory and link are nested further, the directory creation succeeds, while the symlink that is created is broken and points to an incorrect path.

In [1]: def make_dir_and_symlink(dir_relative_to_cwd, sym_relative_to_cwd):
   ...:     os.mkdir(dir_relative_to_cwd)
   ...:     os.symlink(dir_relative_to_cwd, sym_relative_to_cwd)
   ...:     

In [2]: make_dir_and_symlink("test", "test-link")

In [3]: os.path.exists("test")
Out[3]: True

In [4]: os.path.exists("test-link")
Out[4]: True

In [5]: make_dir_and_symlink("test/other-test", "test/other-test-link")

In [6]: os.path.exists("test/other-test")
Out[6]: True

In [7]: os.path.exists("test/other-test-link")
Out[7]: False

Without resorting to any absolute paths in the second example, how can I create a symlink somewhere within a path that is relative to the current working directory?

It appears this can be achieved for a limited situation by combining os.path.relpath and os.path.basename :

def make_dir_and_symlink(dir_relative_to_cwd, sym_relative_to_cwd):
    os.mkdir(dir_relative_to_cwd)
    target_name = os.path.basename(
        os.path.relpath(dir_relative_to_cwd, sym_relative_to_cwd)
    )
    os.symlink(target_name, sym_relative_to_cwd)



In [1]: def make_dir_and_symlink(dir_relative_to_cwd, sym_relative_to_cwd):
   ...:     os.mkdir(dir_relative_to_cwd)
   ...:     os.symlink(os.path.basename(os.path.relpath(dir_relative_to_cwd, sym_relative_to_cwd)), sym_relative_to_cwd)
   ...:     

In [2]: make_dir_and_symlink("test", "test-link")

In [3]: os.path.exists("test")
Out[3]: True

In [4]: os.path.exists("test-link")
Out[4]: True

In [5]: make_dir_and_symlink("test/other-test", "test/other-test-link")

In [6]: os.path.exists("test/other-test")
Out[6]: True

In [7]: os.path.exists("test/other-test-link")
Out[7]: True

This is not expected to handle the general case when the symlink location can be arbitrary with respect to the target location. os.path.basename will only return the immediate base component of the path name, so it works in this situation because it's further assumed that the target and its symlink reside next to each other in the tree starting from the current working directory.

A solution that does not require resolving absolute paths, but still lets the link name be arbitrary within the current working directory relative to the target name is very valuable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM