uilianries
uilianries

Reputation: 3887

How to identify a hardlink using python?

I would like to know if it is possible identify whether a file (or link) is a hardlink or not, on Linux. For instance, If I created:

dd if=/dev/urandom bs=1024 count=10000 of=file_10MB conv=notrunc
ln file_10MB file_10MB_link1

I would like to create a check function, that could be used like this:

if is_hardlink("file_10MB_link1"):
    pass

How can I use Python to check if a file is a hardlink?

Upvotes: 2

Views: 4195

Answers (5)

anthony sottile
anthony sottile

Reputation: 69844

I believe you're looking for "files which have a link count greater than 1"

for that you can use:

def more_than_one_link(filename):
    return os.stat(filename).st_nlink > 1

Upvotes: 10

tomko
tomko

Reputation: 60

It is Possible for windows with the following code:

def is_hardlink(path):
    try:
        os.readlink(path)
        return True
    except:
        return False

For softlinks, directorys and files this comand will raise a error

Upvotes: -2

not2qubit
not2qubit

Reputation: 16912

The answer is that that it depends on the filesystem and (exact) OS you are using. For example, if you are using NTFS (although unlikely in a native Linux context) it allows for a wide range of NTFS specific features including hardlinks and junctions. So while in Windows they use link numbers for hardlinks, Linux OS use inodes.

You would need specific kernel drivers or a forensic OS to be able to read all those, as normal Linux are using only inodes, and would need to be counted and time-stamp analyzed to decide what is the original file vs. a later created hardlink(s).

As python can create both hardlinks and softlinks via:

os.link()    # Create a hard link
os.symlink() # Create a symbolic link

(TL;DR the long docs above) there should be a way for you to check the link type, although it may require quite a bit of disc processing (searching and comparing).

For the exact detection check the built-in os functions, explained in this answer.
[islink(), parse_reparse_buffer(), readlink()]

For all other details on how Windows are making links, please see the excellent web page about the Link Shell Extensions tool.

Either way, you could also use the ctypes python libraries for accessing the Windows API, but would require substantial coding. You may learn a lot more about this here.

Upvotes: 1

ntg
ntg

Reputation: 14075

TL;DR: here is how you do it:

import os
def are_hardlinked(f1, f2):
    if not (os.path.isfile(f1) and os.path.isfile(f2)):
        return False
    return os.path.samefile(f1, f2) or (os.stat(f1).st_ino == os.stat(f2).st_ino)

For linux, by definition, they are hardlinked if they point to the same inode, so comparing st_ino will do.

For windows, first decide what a window respective of a hardlink is ;), then go from there:)... However, it is possible for all reasonable definitions os.path.samefile(f1, f2) will cover you.

Upvotes: 1

Barmar
Barmar

Reputation: 780673

No, it's not possible. There's nothing that distinguishes the original file from the hard link. They're just two names that refer to the same inode number, which represents the file contents.

You can use the code in Anthony Sottile's answer to tell if the file has multiple links to it, but you can't tell which is the original.

Upvotes: 4

Related Questions