1

I have directory factory under which I have app dir app_1_2_3_4. I want to create a symlink under factory for app -> app_1_2_3_4 from /home/user/ dir without using os.chdir(), just like this. Don't want full path in link.

user@ubuntu % ls -l factory/
total 0
lrwxrwxrwx@  1 user  user   13 Mar 15 04:27 app -> app_1_2_3_4
drwxrwxr-x@ 18 user  user  576 Mar 18 17:09 app_1_2_3_4

I tried this in python

import os

app_dir_path = '/home/user/factory' + '/' + 'app'
app_dir_ver_path = '/home/user/factory' + '/../' + 'app' + '_{}_{}_{}_{}'.format(major, minor, bugfix, build)
os.symlink(app_dir_ver_path, app_dir_path)

But this one creating symlink with full path

user@ubuntu % ls -l factory/
total 0
lrwxrwxrwx@  1 user  user   13 Mar 15 04:27 app -> /home/user/factory/app_1_2_3_4
drwxrwxr-x@ 18 user  user  576 Mar 18 17:09 app_1_2_3_4

What I am missing here?

martineau
  • 119,623
  • 25
  • 170
  • 301
roy
  • 6,344
  • 24
  • 92
  • 174

2 Answers2

1

Simply leave out the directory.

$ ls -l factory
total 0
-rw-r--r-- 1 user user 0 mar 18 18:06 app_1_2_3_4

$ python
>>> import os
>>> os.symlink('app_1_2_3_4', 'factory/bar')
>>> quit()

$ ls -l factory/bar
lrwxrwxrwx 1 user user 11 mar 18 18:10 factory/bar -> app_1_2_3_4

By the way, ln -s works the exact same way:

$ ln -s app_1_2_3_4 factory/foo

$ ls -l factory/foo
lrwxrwxrwx 1 user user 11 mar 18 18:09 factory/foo -> app_1_2_3_4
wjandrea
  • 28,235
  • 9
  • 60
  • 81
1

os.symlink() takes an argument dir_fd which is a directory descriptor, from the docs:

If dir_fd is not None, it should be a file descriptor referring to a directory, and the path to operate on should be relative; path will then be relative to that directory.

You can acquire a directory descriptor with help of os.open(), see below.

(Ideally you also want to use f-strings and os.path.join() when joining paths.)

import os

# Assuming you are getting 'app_dir_ver_path' from somewhere else
# and 'major', 'minor', 'bugfix', 'build' are defined.
# "/home/user/factory/app_1_2_3_4"
app_dir_ver_path = os.path.join(
    /home/user/factory,
    f'app_{major}_{minor}_{bugfix}_{build}'
)

# Get the directory where the symlink is supposed to be created:
# "/home/user/factory"
app_dir_ver_name = os.path.dirname(app_dir_ver_path)

# Get the name of the directory to be linked:
# "app_1_2_3_4"
app_dir_ver_base = os.path.basename(app_dir_ver_path)

# Get the directory desciptor:
dir_fd = os.open(app_dir_ver_name, os.O_RDONLY)

# Full path for the symlink:
# "/home/user/factory/app"
app_dir_path = os.path.join(app_dir_ver_name, 'app')

os.symlink(src=app_dir_ver_base, dst=app_dir_path, dir_fd=dir_fd)

Run from anywhere on the system, creates symlink in /home/user/factory:

ls -l /home/user/factory/
lrwxrwxrwx@  1 user  user   13 Mar 15 04:27 app -> app_1_2_3_4
drwxrwxr-x@ 18 user  user  576 Mar 18 17:09 app_1_2_3_4
Paul P
  • 3,346
  • 2
  • 12
  • 26