Periksa apakah file symlink di python

98

Di python, apakah ada fungsi untuk memeriksa apakah file / direktori yang diberikan adalah symlink? Misalnya, untuk file di bawah ini, fungsi pembungkus saya harus kembali 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
sumber

Jawaban:

142

Untuk menentukan apakah entri direktori adalah symlink, gunakan ini:

os.path.islink (jalur)

Kembalikan True jika jalur merujuk ke entri direktori yang merupakan tautan simbolis. Selalu Salah jika tautan simbolik tidak didukung.

Misalnya, diberikan:

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
Levon
sumber
8
Di Windows, Pintasan muncul sebagai file dengan ekstensi lnk, dan os.islink('a_shortcut.lnk')kembali False.
Evgeni Sergeev
1
@EvgeniSergeev Itu karena mereka hanya file - mungkin mabuk dari Windows 9x hari ketika satu-satunya sistem file adalah FAT / FAT32. Lihat superuser.com/questions/347930/… ini untuk semua jenis symbolic / hard link dan directory junction yang didukung pada NTFS. Meski begitu, menurut saya Python masih belum mendukung mereka.
jmc
10
Dan islink () tidak berfungsi untuk symlink Windows, yaitu persimpangan. Jadi jawabannya hanya berlaku untuk Unix.
The Godfather
2
Silakan merujuk ke jawaban stackoverflow.com/questions/27972776/… ini jika Anda membutuhkan solusi Windows.
The Godfather
1
@TheGodfather: persimpangan direktori bukan symlink ( IO_REPARSE_TAG_SYMLINK).
jfs
13

Untuk python 3.4 dan yang lebih baru, Anda dapat menggunakan kelas Path

from pathlib import Path


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

Anda harus berhati-hati saat menggunakan metode is_symlink (). Ini akan mengembalikan True bahkan target tautannya tidak ada selama objek bernama adalah symlink. Misalnya (Linux / Unix):

ln -s ../nonexistentfile flnk

Kemudian, di direktori Anda saat ini, jalankan python

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

Programmer harus memutuskan apa yang sebenarnya dia inginkan. Python 3 tampaknya telah mengganti nama banyak kelas. Mungkin bermanfaat untuk membaca halaman manual untuk kelas Path: https://docs.python.org/3/library/pathlib.html

Kemin Zhou
sumber
ini MUNGKIN hanya menemukan symlink yang valid, ini MUNGKIN tidak mengidentifikasi file yang merupakan symlink tetapi rusak. jadi jika Anda memfilter file nyata atau semua symlink (baik dan buruk) maka pastikan Anda melakukan pemeriksaan tambahan
2114L3
@ 2114L3 Apa yang dimaksud dengan symlink yang valid tetapi rusak? Dari pengujian sederhana dengan symlink yang rusak, tampaknya itu is_symlink()benar, dan exists()salah, itulah yang saya harapkan. Bisakah Anda memberikan sumber untuk kekhawatiran Anda?
Jonathan H
1
@Sheljohn periksa editan pada jawaban ini, sebelum komentar saya ada () bukan bagian dari jawaban. menggunakan ada adalah pemeriksaan tambahan yang saya maksud. karena menggunakan is_symlink saja tidak cukup sesuai versi aslinya.
2114L3
Pada Windows, ini tidak berfungsi dengan benar untuk saya: is_symlinkmengembalikan truefile yang tidak ada (begitu exists()juga mengembalikan true).
James Hirschorn
3

Tanpa niat untuk menggembungkan topik ini, tetapi saya dialihkan ke halaman ini karena saya sedang mencari symlink untuk menemukannya dan mengonversinya menjadi file nyata dan menemukan skrip ini di dalam pustaka alat 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")
pengguna1767754
sumber
Bisakah Anda menjelaskan apa yang terjadi di sini? Kelihatannya aneh karena Anda menghapus (membatalkan tautan) file sebelum benar-benar menulisnya kembali. Bagaimana ini bisa terjadi? Juga yang terakhir mkrealfile(...)berada pada level yang sama dengan fungsinya sendiri ...
not2qubit