2013-03-06 8 views
11

Windows 7でPython 2.7を使用すると、パスがシンボリックリンクかどうかを検出できますか? これはうまくいきません、それはfalseまたはサポートされていない場合はfalseを返し、私が提供しているパスは間違いなくシンボリックリンクなので、私はそれがWindows上でサポートされていないと仮定していると言いますか?私に何ができる?os.path.islink with windows Python

+3

[これ](http://bugs.python.org/issue13143)の提供してもよいですいくつかの助け。 – crayzeewulf

+2

['jaraco.windows'パッケージ](https://bitbucket.org/jaraco/jaraco.windows/src/default/jaraco/windows/filesystem/__init__.py)を見てください。これをサポートするには 'ctypes'を使用しなければなりません。 Python 3.2 *はWindowsのシンボリックリンクを適切にサポートしています。 –

答えて

19

根本的な問題は、古いバージョンのPythonを使用していることです。 2.xに固執したい場合は、2010年初め以降に追加された新機能を利用することはできません。

これらの機能の1つは、NTFSシンボリックリンクを処理することです。この機能は2010年後半には3.2で追加されました(詳細については3.23.1、および2.7ソースを参照してください。)

その後、2009年後半まではそのようなことがなかったということである前に、PythonはNTFSシンボリックリンクを処理しなかった理由を。 (IIRC、6.0カーネルにはサポートが含まれていましたが、ユーザーランドのサポートにはVista/2008のサービスパックが必要ですが、2008/7RR2以降のみに組み込まれています)さらに、新しいものにアクセスするには十分な新しいMSVCRTが必要ですユーザーランドのサポート、Pythonには、マイナーリリース内で新しいVisual Studioのバージョンにアップグレードしないという明示的な方針があります)。

コードが2.xに戻されなかった理由はthat there will never be a 2.8です。 3(または2.7.4)はneを取得しませんw機能、バグ修正のみ。

これはissue 13143と報告されており、意図した解決策は2.7文書を変更してislinkがWindowsで常にFalseを返すことを明確にすることです。

WindowsでNTFSのシンボリックリンクを読むには、Python 3.2以降にアップグレードするか、win32apictypesなどを使用して自分で解決する必要があります。

Martijn Pietersが示唆しているように、自分で行う代わりにjaraco.windowsなどのサードパーティライブラリを使用してください。their codeを借りてください。

本当に必要な場合は、3.2ソースからコードを借りて、C拡張モジュールをビルドします。 ntpathからosnt(実際にはposixmodule.c)までトレースすると、その勇気はwin32_xstat_impl and win32_xstat_impl_wにあると思います。

+0

誰でも落として、理由を説明してくれますか? – abarnert

+0

すごい!ありがとうabarnert – user391986

+0

あなたは間違っている必要があります。 NTFS 3.0のWindows NT 5(Windows 2000)から再解析ポイントが存在します。それは機能的だった。 Pythonの実装は単に怠惰であるか誤解されています。 –

5

これは私がファイルまたはディレクトリは、Windows 7でのリンクであるかどうかを判断するために使用してしまったものです:

def isLink(path): 
    if os.path.exists(path): 
     if os.path.isdir(path): 
      FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 
      attributes = ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) 
      return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) > 0 
     else: 
      command = ['dir', path] 
      try: 
       with open(os.devnull, 'w') as NULL_FILE: 
        o0 = check_output(command, stderr=NULL_FILE, shell=True) 
      except CalledProcessError as e: 
       print e.output 
       return False 
      o1 = [s.strip() for s in o0.split('\n')] 
      if len(o1) < 6: 
       return False 
      else: 
       return 'SYMLINK' in o1[5] 
    else: 
     return False 

EDIT:ディレクトリの場合Zitraxとアナン

+0

ファイルが存在しないときに 'check_output'から' CalledProcessError'をキャッチする価値があります。 'stderr = subprocess.PIPE'を渡して、stdinに行くエラー出力を隠すこともできます。この解決法は本当にハックですが、他の答えよりも実行可能です。 – Annan

+0

この回答は、ディレクトリがリンクであるかどうかを調べるためには機能しません.dirコマンドを実行すると、コンテンツが一覧表示されます。 – Zitrax

+0

@Zitrax: 'dir/al" path * "'は動作します –

5

の提案のとおり変更されたコード:

import os, ctypes 
def IsSymlink(path): 
    FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 
    return os.path.isdir(path) and (ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) & FILE_ATTRIBUTE_REPARSE_POINT): 

Source

+0

ソースが死んでいます – thatsIch

+0

@thatsIch archive.orgキャッシュへのリンクが更新されました。 – Zitrax

+0

あなたはreturn文がないソースを比較します。結果が> 0であるかどうかをチェックし、そうでない場合は結果を1024 – thatsIch