Pythonで親ディレクトリを取得するにはどうすればよいですか?


350

誰かがクロスプラットフォームの方法でPythonのパスの親ディレクトリを取得する方法を教えてもらえますか?例えば

C:\Program Files ---> C:\

そして

C:\ ---> C:\

ディレクトリに親ディレクトリがない場合は、ディレクトリ自体を返します。質問は単純に思えるかもしれませんが、Googleで詳しく調べることはできませんでした。

回答:


481

Python 3.4からの更新

pathlibモジュールを使用します。

from pathlib import Path
path = Path("/here/your/path/file.txt")
print(path.parent)

古い答え

これを試して:

import os.path
print os.path.abspath(os.path.join(yourpath, os.pardir))

どこyourpathあなたが親をしたいパスです。


136
あなたの答えは正しいですが複雑です。os.path.dirnameこの機能は、次のように、あるa+=5-4以上回旋ですa+=1。質問は親ディレクトリのみを要求しました。存在するかどうか、またはシンボリックリンクが邪魔になると想定した真の親ディレクトリは要求しませんでした。
tzot

15
それはos.pardir、ではありませんos.path.pardir
bouteillebleu 2012

9
@bouteillebleu:どちらos.pardiros.path.pardir(それらが同一である)、実際に正しいです。
Eric O Lebigot 2013年

45
@tzot:os.path.dirnameパスに末尾のスラッシュが含まれているかどうかによって、残念ながら異なる結果が得られます。信頼できる結果が必要な場合は、os.path.join上記の方法を使用する必要があります。
Artfunkel 2013年

21
これは明らかにStackOverflowの質問を正当化するのに十分に複雑であるため、組み込み関数としてos.pathライブラリに追加する必要があると思います。
2016年

324

使用os.path.dirname

>>> os.path.dirname(r'C:\Program Files')
'C:\\'
>>> os.path.dirname('C:\\')
'C:\\'
>>>

警告:os.path.dirname()末尾のスラッシュがパスに含まれているかどうかによって、異なる結果が得られます。これは、必要なセマンティクスである場合とそうでない場合があります。Cf. を使用した@kenderの回答os.path.join(yourpath, os.pardir)


6
os.path.dirname(r'C:\Program Files')何?Pythonはファイル 'Program Files'があるディレクトリを提供しているだけです。さらに、それは存在する必要さえありません、見よ:os.path.dirname(r'c:\i\like\to\eat\pie')出力'c:\\i\\like\\to\\eat'
Nick T

41
元の投稿者は、ディレクトリが存在しなければならないことを述べていません。文字列操作以外に何もしないパス名メソッドはたくさんあります。パス名が実際に存在するかどうかを確認するには、ディスクアクセスが必要です。アプリケーションによっては、これが望ましい場合と望ましくない場合があります。
Wai Yip Tung

10
このソリューションは、末尾のos.sepに敏感です。os.sep == '/'と言います。dirname(foo / bar)-> foo、ただしdirname(foo / bar /)-> foo / bar
marcin

6
これは仕様によるものです。末尾に/があるパスの解釈に帰着します。「path1」は「path1 /」と等しいと思いますか?ライブラリは、それらが異なるという最も一般的な解釈を使用します。一部のコンテキストでは、人々はそれらを同等のものとして扱いたいと思うかもしれません。この場合、最初にrstrip( '/')を実行できます。ライブラリが他の解釈を選択した場合、忠実性が失われます。
Wai Yip Tung

3
@ライアン、私はそれについて知りません。URIの相対パスの問題と、末尾の/の有無の微妙な問題に対処するために記述されたRFC 1808全体があります。一般的に同等に扱う必要があると述べているドキュメントを知っている場合は、指摘してください。
Wai Yip Tung

112

Pathlibメソッド(Python 3.4以降)

from pathlib import Path
Path('C:\Program Files').parent
# Returns a Pathlib object

伝統的な方法

import os.path
os.path.dirname('C:\Program Files')
# Returns a string


どの方法を使用する必要がありますか?

次の場合は、従来の方法を使用します。

  • Pathlibオブジェクトを使用する場合、既存のコードがエラーを生成することを心配しています。(Pathlibオブジェクトは文字列と連結できないため。)

  • Pythonのバージョンが3.4未満です。

  • 文字列が必要で、文字列を受け取りました。たとえば、ファイルパスを表す文字列があり、JSON文字列に配置できるように親ディレクトリを取得するとします。Pathlibオブジェクトに変換し、そのために再び戻るのは、ばかげたことでしょう。

上記のいずれにも該当しない場合は、Pathlibを使用してください。



Pathlibとは何ですか?

Pathlibが何であるかわからない場合、Pathlibモジュールは、ファイルの操作をさらに簡単にする素晴らしいモジュールです。ファイルで機能する組み込みのPythonモジュールのすべてではないにしても、ほとんどがPathlibオブジェクトと文字列の両方を受け入れます。以下に、Pathlibのドキュメントから抜粋して、Pathlibを使用して実行できる優れた機能のいくつかを紹介します。

ディレクトリツリー内を移動する:

>>> p = Path('/etc')
>>> q = p / 'init.d' / 'reboot'
>>> q
PosixPath('/etc/init.d/reboot')
>>> q.resolve()
PosixPath('/etc/rc.d/init.d/halt')

パスプロパティのクエリ:

>>> q.exists()
True
>>> q.is_dir()
False

4
これが唯一の正解です。Python 2を使わざるを得ない場合はpip install pathlib2、バックポートを使用してください。
Navin 2017年

1
このソリューションは末尾に影響されませんos.sep
ディランF

35
import os
p = os.path.abspath('..')

C:\Program Files ---> C:\\\

C:\ ---> C:\\\


7
これは、OPが要求した任意のパスの親ではなく、CWDの親のみを取得します。
セルジオ

URLの最後に二重ドットを追加すると、たとえば次のように機能します。例 os.path.abspath(r'E:\O3M_Tests_Embedded\branches\sw_test_level_gp\test_scripts\..\..')E:\\O3M_Tests_Embedded\\branches
Arindam Roychowdhury

つまり、です/
loretoparisi

26

@kenderの代替ソリューション

import os
os.path.dirname(os.path.normpath(yourpath))

どこyourpathあなたが親をしたいパスです。

しかし、このソリューションはyourpath、が空の文字列またはドットである場合を処理しないため、完全ではありません。

この他のソリューションは、このコーナーケースをよりうまく処理します:

import os
os.path.normpath(os.path.join(yourpath, os.pardir))

ここで、見つけることができるすべてのケースの出力(入力パスは相対です):

os.path.dirname(os.path.normpath('a/b/'))          => 'a'
os.path.normpath(os.path.join('a/b/', os.pardir))  => 'a'

os.path.dirname(os.path.normpath('a/b'))           => 'a'
os.path.normpath(os.path.join('a/b', os.pardir))   => 'a'

os.path.dirname(os.path.normpath('a/'))            => ''
os.path.normpath(os.path.join('a/', os.pardir))    => '.'

os.path.dirname(os.path.normpath('a'))             => ''
os.path.normpath(os.path.join('a', os.pardir))     => '.'

os.path.dirname(os.path.normpath('.'))             => ''
os.path.normpath(os.path.join('.', os.pardir))     => '..'

os.path.dirname(os.path.normpath(''))              => ''
os.path.normpath(os.path.join('', os.pardir))      => '..'

os.path.dirname(os.path.normpath('..'))            => ''
os.path.normpath(os.path.join('..', os.pardir))    => '../..'

入力パスは絶対パスです(Linuxパス):

os.path.dirname(os.path.normpath('/a/b'))          => '/a'
os.path.normpath(os.path.join('/a/b', os.pardir))  => '/a'

os.path.dirname(os.path.normpath('/a'))            => '/'
os.path.normpath(os.path.join('/a', os.pardir))    => '/'

os.path.dirname(os.path.normpath('/'))             => '/'
os.path.normpath(os.path.join('/', os.pardir))     => '/'

パスを正規化することは、特にクロスプラットフォームの作業を行うときに、常に良い習慣です。
DevPlayer 2016年

これが正解です。相対パスを相対的に保ちます。ありがとう!
Maximの

@Maximこのソリューションは完璧ではありませんでした。元のソリューションは1つのケースを処理しないため、改善しました
ベンジャロビン'27年

@benjarobinはい、私はコーナーケースを考えていませんでした。ありがとう。
Maxim

18
os.path.split(os.path.abspath(mydir))[0]

これは、ディレクトリへのパスでは機能せず、ディレクトリを再び返すだけです。
Anthony Briggs

2
@ AnthonyBriggs、Ubuntu 12.04でPython 2.7.3を使用して試したところ、問題なく動作するようです。期待どおりにos.path.split(os.path.abspath("this/is/a/dir/"))[0]戻ります'/home/daniel/this/is/a'。現在のところ、そこで実行するWindowsボックスを実行していません。あなたが報告する行動をどのような設定で観察しましたか?
Dan Menes

あなたがすることができますparentdir = os.path.split(os.path.apspath(dir[:-1]))[0]。これ-私は確信しています-スラッシュが最後にある場合、それは削除されるので機能します スラッシュがない場合でも、前のスラッシュのため、これは(パスの最後の部分が1文字しかない場合でも)機能します。もちろん、これはパスが適切であり、/a//b/c///d////(UNIXではこれはまだ有効です)のようなことを言っていないことを前提としています。ほとんどの場合、特に何かos.path.abspath他のos.path機能を実行するときに(適切)です。
dylnmc 2014年

また、最後に多くのスラッシュを打ち消すには、それらを削除する小さなforループを書くだけです。私はそれを行うための賢いワンライナーがあるかもしれないと確信しています、または多分それを行い、os.path.splitを一行に入れます。
dylnmc 2014年

@Den Menes私はあなたのコメントを見たところです。os.path.split("a/b//c/d///")たとえばcd //////dev////// is equivalent to cd / dev / `やcd /dev;のようなものがある場合は機能しません。これらはすべてLinuxで有効です。私はこれを思いついたばかりですが、それは便利かもしれません:os.path.split(path[:tuple(ind for ind, char in enumerate(path) if char != "/" and char != "\\")[-1]])[0]。(これは基本的に最後の非スラッシュを検索し、その文字までのパスの部分文字列を取得します。)私path = "/a//b///c///d////"は前述のステートメントを使用して実行し、を取得しました'/a//b///c'
dylnmc 2014年

14
os.path.abspath(os.path.join(somepath, '..'))

観察する:

import posixpath
import ntpath

print ntpath.abspath(ntpath.join('C:\\', '..'))
print ntpath.abspath(ntpath.join('C:\\foo', '..'))
print posixpath.abspath(posixpath.join('/', '..'))
print posixpath.abspath(posixpath.join('/home', '..'))

7
import os
print"------------------------------------------------------------"
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
print("example 1: "+SITE_ROOT)
PARENT_ROOT=os.path.abspath(os.path.join(SITE_ROOT, os.pardir))
print("example 2: "+PARENT_ROOT)
GRANDPAPA_ROOT=os.path.abspath(os.path.join(PARENT_ROOT, os.pardir))
print("example 3: "+GRANDPAPA_ROOT)
print "------------------------------------------------------------"

6

引数として提供されるファイルの直接の親であり、そのファイルへの絶対パスではないフォルダーの名前のみが必要な場合:

os.path.split(os.path.dirname(currentDir))[1]

つまり、currentDir/home/user/path/to/myfile/file.ext

上記のコマンドは次を返します:

myfile


3
os.path.basename(os.path.dirname(current_dir))もここで機能します。
DevPlayer 2016年

4
>>> import os
>>> os.path.basename(os.path.dirname(<your_path>))

たとえば、Ubuntuの場合:

>>> my_path = '/home/user/documents'
>>> os.path.basename(os.path.dirname(my_path))
# Output: 'user'

たとえば、Windowsの場合:

>>> my_path = 'C:\WINDOWS\system32'
>>> os.path.basename(os.path.dirname(my_path))
# Output: 'WINDOWS'

Python 2.7で両方の例を試しました


3
import os.path

os.path.abspath(os.pardir)

これは、「現在の作業ディレクトリ」の親ディレクトリが必要であり、一般に親ディレクトリがパスではないことを前提としています。
DevPlayer 2016年

3

次のようなディレクトリ構造があるとします。

1]

/home/User/P/Q/R

ディレクトリRから "P"のパスにアクセスしたい場合は、次を使用してアクセスできます。

ROOT = os.path.abspath(os.path.join("..", os.pardir));

2]

/home/User/P/Q/R

ディレクトリRから「Q」ディレクトリのパスにアクセスしたい場合は、次を使用してアクセスできます。

ROOT = os.path.abspath(os.path.join(".", os.pardir));

2

Tungの答えに何かを追加するだけです(rstrip('/')UNIXボックスを使用している場合は、これを使用して安全性を高める必要があります)。

>>> input = "../data/replies/"
>>> os.path.dirname(input.rstrip('/'))
'../data'
>>> input = "../data/replies"
>>> os.path.dirname(input.rstrip('/'))
'../data'

ただし、を使用しない場合rstrip('/')、入力が

>>> input = "../data/replies/"

出力します、

>>> os.path.dirname(input)
'../data/replies'

これはあなたが両方をしたいようで、探しているものはおそらくない"../data/replies/""../data/replies"同じように動作します。


1
変数/参照として「入力」を使用しないことをお勧めします。組み込み関数です。
DevPlayer 2016年

2
import os

dir_path = os.path.dirname(os.path.realpath(__file__))
parent_path = os.path.abspath(os.path.join(dir_path, os.pardir))

1
print os.path.abspath(os.path.join(os.getcwd(), os.path.pardir))

これを使用して、pyファイルの現在の場所の親ディレクトリを取得できます。


2
その提案はしばしばバグにつながります。os.getcwd()は多くの場合、「your py file」の場所にはありません。パッケージを考えてください。「some_package_with_subpackagesをインポートする」と、多くのモジュールがそのパッケージの最上位ディレクトリにありません。os.getcwd()は、最上位のスクリプトを実行した場所を返します。また、コマンドラインから実行していることも前提としています。
DevPlayer 2016年

0

親ディレクトリのパス取得し、新しいディレクトリ(名前new_dir)を作成します

親ディレクトリのパスを取得

os.path.abspath('..')
os.pardir

例1

import os
print os.makedirs(os.path.join(os.path.dirname(__file__), os.pardir, 'new_dir'))

例2

import os
print os.makedirs(os.path.join(os.path.dirname(__file__), os.path.abspath('..'), 'new_dir'))


0
import os

def parent_filedir(n):
    return parent_filedir_iter(n, os.path.dirname(__file__))

def parent_filedir_iter(n, path):
    n = int(n)
    if n <= 1:
        return path
    return parent_filedir_iter(n - 1, os.path.dirname(path))

test_dir = os.path.abspath(parent_filedir(2))

0

上記の回答は、1つまたは2つのディレクトリレベルを上げるのに完全に適していますが、ディレクトリツリーを多数のレベル(たとえば、5または10)トラバースする必要がある場合は、少し面倒になることがあります。これは、リスト結合することにより簡潔に行うことができますN os.pardirsでos.path.join。例:

import os
# Create list of ".." times 5
upup = [os.pardir]*5
# Extract list as arguments of join()
go_upup = os.path.join(*upup)
# Get abspath for current file
up_dir = os.path.abspath(os.path.join(__file__, go_upup))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.