2012-03-22 17 views
7

現在のディレクトリから始めて、特定のファイルを含むディレクトリを検索するスクリプトがあります(.gitディレクトリがどこにあるのか調べようとしています) )。ディレクトリが(ファイルシステムの)ルートであることを確認してください

私の方法は、次のようになります。どうやら/..に参加すると、あなたを与えるため

def getDir(self,cwd): 
    path = os.path.abspath(cwd) 
    if not os.path.isdir(path): 
    raise RuntimeError("getDir should not be run on files") 
    if FILE in os.listdir(path): 
    return path 
    parent = os.path.join(path, os.path.pardir) 
    if os.access(parent, os.R_OK) and os.access(parent, os.X_OK): 
    return self.getDir(parent) 
    else 
    return None 

今、この方法の問題は、それがディレクトリを見つけることができない場合、それはループ(そして最終的にスタックオーバーフロー)、ということです/。私はpathparentまたはそれらのreprを比較しようとしましたが、それはうまくいかなかった(常に異なっていた)。私の回避策は、再帰的メソッドに深さカウンタを組み込み、ランダムな最大しきい値で停止することです。

私の質問は、ファイルシステムのルートに達しているかどうかを確認する信頼できるクロスプラットフォームの方法ですか?

+1

すべてのプラットフォームで信頼できるかどうかは完全にはわかりませんが、os.path.dirname(path)== pathの場合、pathはルートのようです。 –

答えて

7

ファイルシステムのルートが移植可能かどうかはわかりませんが、私は現在のディレクトリと計算された親ディレクトリの両方でos.path.realpath()への呼び出しを行い、これは、あなたがあなたの車輪を回転させていることを意味し、進行中のポイントはありません。例えば

>>> os.path.realpath('/usr/bin/..') 
'/usr' 
>>> os.path.realpath('/usr/bin/../..') 
'/' 
>>> os.path.realpath('/usr/bin/../../..') 
'/' 
>>> os.path.realpath('/..') 
'/' 
16
if os.path.dirname(path) == path: 
    # you have yourself root. 
    # works on Windows and *nix paths. 
    # does NOT work on Windows shares (\\server\share) 
+1

Windows共有では動作しますが、共有がルートになるとは表示されません。ルートとして\\ serverが考えられます。とにかくそれは正直なところ、IMOを意味します。 –

+0

@nacitarsevahtあなたはおそらく正しいでしょう。ルートとして\\ serverを考えるのは理にかなっていますが、 "list dir"を実行する通常のツールを通して\\ serverの内容を列挙することはほとんど実用的ではないので、あまり実用的ではありません。 – ddotsenko

+0

パスに ".."要素が含まれていると、この回答は機能しません(例:@ FatalErrorの回答)。 – jmh

1

これは、Linux上で私たちのために動作します。ただし、Windowsについてはわかりません:

def _find_root(start, stop, func=os.path.exists): 
    """Search up the start hierarchy for stop; return None at the FS root. 

    Uses func() to determine if stop exists; default is os.path.exists(). 
    """ 
    if func(os.path.join(start, stop)): 
     return start 
    else: 
     if os.path.samefile(start, os.path.dirname(start)): 
      return None 
     else: 
      return _find_root(os.path.dirname(start), stop) 

この関数の呼び出しでは、os.path.normpath(start)を使用します。

関連する問題