Creating a relative symlink in python without using os.chdir()
Question:
Say I have a path to a file:
/path/to/some/directory/file.ext
In python, I’d like to create a symlink in the same directory as the file, that
points to the file. I’d like to end up with this:
/path/to/some/directory/symlink -> file.ext
I can do this fairly easily using os.chdir() to cd into the directory and
create the symlinks. But os.chdir() is not thread safe, so I’d like to avoid
using it. Assuming that the current working directory of the process is not
the directory with the file (os.getcwd() != ‘/path/to/some/directory’),
what’s the best way to do this?
I guess I could create a busted link in whatever directory I’m in, then
move it to the directory with the file:
import os, shutil
os.symlink('file.ext', 'symlink')
shutil.move('symlink', '/path/to/some/directory/.')
Is there a better way to do this?
Note, I don’t want to end up with is this:
/path/to/some/directory/symlink -> /path/to/some/directory/file.ext
Answers:
You could just set the second argument to the destination, like:
import os
os.symlink('file.ext', '/path/to/some/directory/symlink')
You can also use os.path.relpath()
so that you can use symlinks with relative paths. Say your script is in a directory foo/
and this directory has subdirectories src/
and dst/
, and you want to create relative symlinks in dst/
to point to the files in src/
. To do so, you can do:
import os
from glob import glob
for src_path in glob('src/*'):
os.symlink(
os.path.relpath(
src_path,
'dst/'
),
os.path.join('dst', os.path.basename(src_path))
)
Listing the contents of dst/
then shows:
1.txt -> ../src/1.txt
2.txt -> ../src/2.txt
Relative symlinks are useful for if you want to create a tarball of the whole foo
directory tree, as I don’t believe tar
updates symlinks to point to the relative path inside of the generated tarball.
python function to create a relative symlink:
def relative_symlink(src, dst):
dir = os.path.dirname(dst)
Src = os.path.relpath(src, dir)
Dst = os.path.join(dir, os.path.basename(src))
return os.symlink(Src, Dst)
Nowadays, this can be accomplished using pathlib
from pathlib import Path
target = Path('../target.txt')
my_symlink = Path('symlink.txt')
my_symlink.symlink_to(target)
where target
is a relative Path
or str
.
Say I have a path to a file:
/path/to/some/directory/file.ext
In python, I’d like to create a symlink in the same directory as the file, that
points to the file. I’d like to end up with this:
/path/to/some/directory/symlink -> file.ext
I can do this fairly easily using os.chdir() to cd into the directory and
create the symlinks. But os.chdir() is not thread safe, so I’d like to avoid
using it. Assuming that the current working directory of the process is not
the directory with the file (os.getcwd() != ‘/path/to/some/directory’),
what’s the best way to do this?
I guess I could create a busted link in whatever directory I’m in, then
move it to the directory with the file:
import os, shutil
os.symlink('file.ext', 'symlink')
shutil.move('symlink', '/path/to/some/directory/.')
Is there a better way to do this?
Note, I don’t want to end up with is this:
/path/to/some/directory/symlink -> /path/to/some/directory/file.ext
You could just set the second argument to the destination, like:
import os
os.symlink('file.ext', '/path/to/some/directory/symlink')
You can also use os.path.relpath()
so that you can use symlinks with relative paths. Say your script is in a directory foo/
and this directory has subdirectories src/
and dst/
, and you want to create relative symlinks in dst/
to point to the files in src/
. To do so, you can do:
import os
from glob import glob
for src_path in glob('src/*'):
os.symlink(
os.path.relpath(
src_path,
'dst/'
),
os.path.join('dst', os.path.basename(src_path))
)
Listing the contents of dst/
then shows:
1.txt -> ../src/1.txt
2.txt -> ../src/2.txt
Relative symlinks are useful for if you want to create a tarball of the whole foo
directory tree, as I don’t believe tar
updates symlinks to point to the relative path inside of the generated tarball.
python function to create a relative symlink:
def relative_symlink(src, dst):
dir = os.path.dirname(dst)
Src = os.path.relpath(src, dir)
Dst = os.path.join(dir, os.path.basename(src))
return os.symlink(Src, Dst)
Nowadays, this can be accomplished using pathlib
from pathlib import Path
target = Path('../target.txt')
my_symlink = Path('symlink.txt')
my_symlink.symlink_to(target)
where target
is a relative Path
or str
.