Problem
I have a script that creates symlinks from files to a directory. After some time, following a migration to another system, I realized dangling links were silently created.
Demo
To illustrate, the following code will run without exception on Python 3.8, 3.10:
>>> from pathlib import Path
>>> src_filepath = Path("/no/such/file.py")
>>> dest_filepath = Path("any_name_is_ok.py")
>>> dest_filepath.symlink_to(src_filepath)
The result is a symlink that points to a non-existing target /no/such/file.py
.
λ ls -al any_names_ok.py
lrwxrwxrwx 1 root root 16 Sep 3 09:26 any_name_is_ok.py -> /no/such/file.py
I would expect an immediate exception to prevent the link from being created altogether.
Solution
Thankfully, we can assert that symbolic links are made from existing paths:
>>> src_filepath = Path("/no/such/file.py")
>>> dest_filepath = Path("any_names_ok.py")
>>> assert src_filepath.exists(), "No file found."
>>> dest_filepath.symlink_to(src_filepath)
AssertionError: No file found.
Can this be simplified?
Proposal
We could mitigate creation of dangling links through adding an explicit strict=True
parameter to Path.symlink_to(...)
. If the source file/directory does not exist, throw a FileNotFound
error. Example:
# Pseudo-code
>>> src_filepath = Path("/dotfiles/bashrc").expanduser() # missing ~
>>> dest_filepath = Path("~/.bashrc").expanduser()
>>> dest_filepath.symlink_to(src_filepath, strict=True)
FileNotFoundError: '/dotfiles/bashrc' does not exist. A dangling link was prevented.
If the traditional behavior is desired, the default parameter can be set strict=False
.
See Also