ตรวจสอบว่าไฟล์เป็น symlink ใน python หรือไม่


98

ใน python มีฟังก์ชั่นตรวจสอบว่าไฟล์ / ไดเร็กทอรีที่กำหนดเป็น symlink หรือไม่? 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

คำตอบ:


142

ในการตรวจสอบว่ารายการไดเร็กทอรีเป็น symlink หรือไม่ให้ใช้สิ่งนี้:

os.path.islink (เส้นทาง)

ส่งกลับ True ถ้าพา ธ อ้างถึงรายการไดเร็กทอรีที่เป็นลิงก์สัญลักษณ์ เท็จเสมอหากไม่รองรับลิงก์สัญลักษณ์

ตัวอย่างเช่นกำหนด:

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
Evgeni Sergeev

1
@EvgeniSergeev นั่นเป็นเพราะไฟล์เหล่านี้เป็นเพียงไฟล์ - อาจเป็นอาการเมาค้างจาก Windows 9x วันเมื่อระบบไฟล์เดียวคือ FAT / FAT32 โปรดดูsuperuser.com/questions/347930/…สำหรับลิงก์สัญลักษณ์ / ฮาร์ดและจุดเชื่อมต่อไดเร็กทอรีทุกประเภทที่รองรับบน NTFS ที่กล่าวมาฉันยังไม่คิดว่า Python รองรับพวกเขา
jmc

10
และ islink () ใช้ไม่ได้กับลิงก์สัญลักษณ์ของ Windows นั่นคือทางแยก ดังนั้นคำตอบจึงใช้ได้กับ Unix เท่านั้น
The Godfather

2
โปรดดูที่คำตอบstackoverflow.com/questions/27972776/…หากคุณต้องการโซลูชัน Windows
เจ้าพ่อ

1
@TheGodfather: ทางแยกไดเรกทอรีไม่ใช่ symlink ( 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 แม้ว่าเป้าหมายของลิงก์จะไม่มีอยู่ตราบใดที่อ็อบเจ็กต์ที่ระบุชื่อนั้นเป็น symlink ตัวอย่างเช่น (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


อาจพบเฉพาะ symlink ที่ถูกต้องซึ่งอาจไม่ระบุไฟล์ที่เป็น symlink แต่เสีย ดังนั้นหากคุณกำลังกรองไฟล์จริงหรือ symlink ทั้งหมด (ดีและไม่ดี) ให้ตรวจสอบเพิ่มเติม
2114L3

@ 2114L3 symlink ที่ถูกต้อง แต่เสียหมายความว่าอย่างไร จากการทดสอบอย่างง่ายด้วย symlink ที่ใช้งานไม่ได้ดูเหมือนว่าis_symlink()จะเป็นจริงและexists()เป็นเท็จซึ่งเป็นสิ่งที่ฉันคาดหวัง คุณสามารถให้แหล่งข้อมูลสำหรับข้อกังวลของคุณได้หรือไม่?
Jonathan H

1
@Sheljohn ตรวจสอบการแก้ไขในคำตอบนี้ก่อนที่ความคิดเห็นของฉันจะมีอยู่ () ไม่ใช่ส่วนหนึ่งของคำตอบ การใช้มีอยู่เป็นการตรวจสอบเพิ่มเติมที่ฉันหมายถึง เนื่องจากการใช้ is_symlink เพียงอย่างเดียวไม่เพียงพอตามเวอร์ชันดั้งเดิม
2114L3

ใน Windows สิ่งนี้ทำงานไม่ถูกต้องสำหรับฉัน: is_symlinkกำลังส่งคืนtrueไฟล์ที่ไม่มีอยู่ ( exists()ส่งคืนด้วยtrue)
James Hirschorn

3

โดยไม่ได้ตั้งใจที่จะขยายหัวข้อนี้ แต่ฉันถูกเปลี่ยนเส้นทางไปยังหน้านี้เนื่องจากฉันกำลังมองหา symlink เพื่อค้นหาและแปลงเป็นไฟล์จริงและพบสคริปต์นี้ในไลบรารี python tools

#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")

คุณอธิบายได้ไหมว่าเกิดอะไรขึ้นที่นี่? มันดูแปลก ๆ เพราะดูเหมือนว่าคุณกำลังลบ (ยกเลิกการลิงก์) ไฟล์ก่อนที่จะเขียนกลับจริงๆ แบบนี้ได้ยังไง? สุดท้ายmkrealfile(...)ยังอยู่ในระดับเดียวกับฟังก์ชันของตัวเอง ...
not2qubit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.