Skip to content

Clarify os.link behavior with follow_symlinks=True on POSIX systems #138623

@guanjiesun

Description

@guanjiesun

Software environemnt

  • Python info: Python 3.13.5 | packaged by conda-forge | (main, Jun 16 2025, 08:27:50) [GCC 13.3.0]
  • OS info: Linux ubuntu 6.8.0-78-generic

A small problem I found in the document about os.link function

The current documentation for os.link states:

If follow_symlinks is False, and the last element of src is a symbolic link,
link will create a link to the symbolic link itself instead of the file the link points to.

This wording suggests that if follow_symlinks=True (the default), the call will follow
the symlink and create a hard link to the target file.

However, on POSIX systems (e.g., Linux), this is not what actually happens.
The underlying link(2) system call never follows symbolic links — it always creates
a hard link to the symlink itself. As a result, on Linux, whether follow_symlinks is True or False, the result is the same.

os.link("symlink", "dst")
os.link("symlink", "dst", follow_symlinks=False)

A simple experiment

Experiment result is presented as below. shell.py is a regular file and soft is the symbolic link to shell.py. soft, link-with-true, link-with-false have the same inode and they are all softlinks to shell.py.

Image

Suggested documentation update

To avoid confusion, please update the os.link documentation to note that:

  • On POSIX systems (such as Linux), the underlying link(2) system call never follows symbolic links.
  • Therefore, follow_symlinks=True and follow_symlinks=False behave the same: both create a hard link to the symlink itself, not to its target.
  • If users want to create a hard link to the target of a symlink, they need to resolve it first with os.readlink().

Metadata

Metadata

Assignees

No one assigned

    Labels

    docsDocumentation in the Doc dirpendingThe issue will be closed if no feedback is provided

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions