Проверьте, является ли файл символической ссылкой в ​​python

98

В python есть функция для проверки, является ли данный файл / каталог символической ссылкой? Например, для файлов ниже должна вернуть моя функция-оболочка True.

# ls -l
total 0
lrwxrwxrwx 1 root root 8 2012-06-16 18:58 dir -> ../temp/
lrwxrwxrwx 1 root root 6 2012-06-16 18:55 link -> ../log
Bandicoot
источник

Ответы:

142

Чтобы определить, является ли запись каталога символической ссылкой, используйте это:

os.path.islink (путь)

Верните True, если путь относится к записи каталога, которая является символической ссылкой. Всегда False, если символические ссылки не поддерживаются.

Например, учитывая:

drwxr-xr-x   2 root root  4096 2011-11-10 08:14 bin/
drwxrwxrwx   1 root root    57 2011-07-10 05:11 initrd.img -> boot/initrd.img-2..

>>> import os.path
>>> os.path.islink('initrd.img')
True
>>> os.path.islink('bin')
False
Левон
источник
8
В Windows ярлыки отображаются как файлы с расширением lnkи os.islink('a_shortcut.lnk')возвращаются False.
Евгений Сергеев
1
@EvgeniSergeev Это потому, что это просто файлы - возможно, пережиток дней Windows 9x, когда единственной файловой системой была FAT / FAT32. См. Этот superuser.com/questions/347930/… для всех типов символических / жестких ссылок и соединений каталогов, поддерживаемых в NTFS. Тем не менее, я все еще не думаю, что Python их поддерживает.
jmc
10
И islink () не работает для символических ссылок Windows, то есть соединений. Так что ответ применим только для Unix.
Крестный отец
2
Пожалуйста, обратитесь к этому ответу stackoverflow.com/questions/27972776/…, если вам нужно решение для Windows.
Крестный отец
1
@TheGodfather: соединение каталогов не является символической ссылкой ( IO_REPARSE_TAG_SYMLINK).
jfs
13

Для python 3.4 и выше вы можете использовать класс Path

from pathlib import Path


# rpd is a symbolic link
>>> Path('rdp').is_symlink()
True
>>> Path('README').is_symlink()
False

Будьте осторожны при использовании метода is_symlink (). Он вернет True, даже если цель ссылки не существует, пока названный объект является символической ссылкой. Например (Linux / Unix):

ln -s ../nonexistentfile flnk

Затем в вашем текущем каталоге запустите python

>>> from pathlib import Path
>>> Path('flnk').is_symlink()
True
>>> Path('flnk').exists()
False

Программист должен решить, чего он действительно хочет. Python 3, похоже, переименовал множество классов. Возможно, стоит прочитать страницу руководства для класса Path: https://docs.python.org/3/library/pathlib.html

Кемин Чжоу
источник
это МОЖЕТ найти только действительную символическую ссылку, это МОЖЕТ не идентифицировать файл, который является символической ссылкой, но не работает. поэтому, если вы фильтруете реальные файлы или все символические ссылки (хорошие и плохие), убедитесь, что вы выполняете дополнительные проверки
2114L3
@ 2114L3 Что означает действительная, но неработающая символическая ссылка? Из простого тестирования с неработающей символической ссылкой кажется, что is_symlink()это правда, и exists()ложно, чего я и ожидал. Можете ли вы указать источник своих опасений?
Jonathan H
1
@Sheljohn проверьте правки в этом ответе, прежде чем мой комментарий существует () не был частью ответа. Использование существует - это дополнительная проверка, о которой я имел в виду. поскольку использование только is_symlink недостаточно в соответствии с исходной версией.
2114L3 02
В Windows это работает неправильно для меня: is_symlinkвозвращается trueдля несуществующих файлов (поэтому exists()также возвращается true).
Джеймс Хиршорн
3

Без намерения раздувать эту тему, но я был перенаправлен на эту страницу, так как искал символические ссылки, чтобы найти их и преобразовать в реальные файлы, и нашел этот скрипт в библиотеке инструментов python.

#Source https://github.com/python/cpython/blob/master/Tools/scripts/mkreal.py


import sys
import os
from stat import *

BUFSIZE = 32*1024

def mkrealfile(name):
    st = os.stat(name) # Get the mode
    mode = S_IMODE(st[ST_MODE])
    linkto = os.readlink(name) # Make sure again it's a symlink
    f_in = open(name, 'r') # This ensures it's a file
    os.unlink(name)
    f_out = open(name, 'w')
    while 1:
        buf = f_in.read(BUFSIZE)
        if not buf: break
        f_out.write(buf)
    del f_out # Flush data to disk before changing mode
    os.chmod(name, mode)

    mkrealfile("/Users/test/mysymlink")
user1767754
источник
Вы можете объяснить, что здесь происходит? Это выглядит довольно странно, поскольку кажется, что вы удаляете (отключаете) файл перед его фактической записью. Как это может быть? Также последний mkrealfile(...)находится на том же уровне, что и его собственная функция ...
not2qubit