Pythonリストディレクトリ、サブディレクトリ、ファイル


130

特定のディレクトリ内のすべてのディレクトリ、サブディレクトリ、およびファイルを一覧表示するスクリプトを作成しようとしています。
私はこれを試しました:

import sys,os

root = "/home/patate/directory/"
path = os.path.join(root, "targetdirectory")

for r,d,f in os.walk(path):
    for file in f:
        print os.path.join(root,file)

残念ながら、正しく動作しません。
すべてのファイルを取得しますが、完全なパスは取得しません。

たとえば、dir構造体は次のようになります。

/home/patate/directory/targetdirectory/123/456/789/file.txt

それは印刷します:

/home/patate/directory/targetdirectory/file.txt

私が必要なのは最初の結果です。どんな助けでも大歓迎です!ありがとう。

回答:


225

ディレクトリとファイルos.path.joinを連結するために使用します。

for path, subdirs, files in os.walk(root):
    for name in files:
        print os.path.join(path, name)

の使用は正しくないため、連結ではpathなく、の使用に注意してください。rootroot


Python 3.4では、パス操作を簡単にするためにpathlibモジュールが追加されました。したがって、同等のものos.path.joinは次のようになります。

pathlib.PurePath(path, name)

の利点はpathlib、パスに対してさまざまな便利なメソッドを使用できることです。具体的なPathバリアントを使用する場合、ディレクトリへのチャンド、パスの削除、それが指すファイルのオープンなど、それらを介して実際のOS呼び出しを行うこともできます。


これは、「Pythonですべてのファイルを再帰的に取得する方法」に関して寄せられた多くの質問に対する唯一かつ有用な回答です。
harrisonfooord

内包リスト:all_files = [パスのファイルの名前、サブディレクトリ、os.walk(folder)のファイルのos.path.join(path、name)]
Nir

45

念のため...あるパターンに一致するディレクトリとサブディレクトリ内のすべてのファイルを取得する(たとえば、*。py):

import os
from fnmatch import fnmatch

root = '/some/directory'
pattern = "*.py"

for path, subdirs, files in os.walk(root):
    for name in files:
        if fnmatch(name, pattern):
            print os.path.join(path, name)

10

ここにワンライナーがあります:

import os

[val for sublist in [[os.path.join(i[0], j) for j in i[2]] for i in os.walk('./')] for val in sublist]
# Meta comment to ease selecting text

最も外側のval for sublist in ...ループは、リストを1次元にフラット化します。jループは、すべてのファイルのベース名のリストを収集し、現在のパスに結合します。最後に、iループはすべてのディレクトリとサブディレクトリを反復します。

この例では、ハードコーディングされたパスを使用./してos.walk(...)呼び出し、あなたが好きなパス文字列を補完することができます。

注:os.path.expanduserおよび/またはos.path.expandvarsパスの文字列に使用できます~/

この例を拡張すると:

ファイルのベース名テストとディレクトリ名テストを簡単に追加できます。

たとえば、*.jpgファイルのテスト:

... for j in i[2] if j.endswith('.jpg')] ...

さらに、.gitディレクトリを除外します。

... for i in os.walk('./') if '.git' not in i[0].split('/')]

動作しますが、.git directoyを除外するには、「。git」がパスに含まれていないかどうかを確認する必要があります。
Roman Rdgz

うん。'.git'がi [0] .split( '/')にない場合]
Roman Rdgz

私はos.walk手動のdirlistingループよりもお勧めします、ジェネレーターは素晴らしいです、それらを使用してください。
ThorSummoner 16

9

コメントできなかったので、ここに回答を書いてください。これは、私が見た中で最も明確な1行です。

import os
[os.path.join(path, name) for path, subdirs, files in os.walk(root) for name in files]

4

私が作ったこのサンプルをご覧ください。使用されなくなったos.path.walk関数を使用します。リストを使用してすべてのファイルパスを保存します

root = "Your root directory"
ex = ".txt"
where_to = "Wherever you wanna write your file to"
def fileWalker(ext,dirname,names):
    '''
    checks files in names'''
    pat = "*" + ext[0]
    for f in names:
        if fnmatch.fnmatch(f,pat):
            ext[1].append(os.path.join(dirname,f))


def writeTo(fList):

    with open(where_to,"w") as f:
        for di_r in fList:
            f.write(di_r + "\n")






if __name__ == '__main__':
    li = []
    os.path.walk(root,fileWalker,[ex,li])

    writeTo(li)

4

少しシンプルなワンライナー:

import os
from itertools import product, chain

chain.from_iterable([[os.sep.join(w) for w in product([i[0]], i[2])] for i in os.walk(dir)])

2

ここでのすべての例はwalkjoin)を使用しているだけなので、素晴らしい例と比較してみましょうlistdir

import os, time

def listFiles1(root): # listdir
    allFiles = []; walk = [root]
    while walk:
        folder = walk.pop(0)+"/"; items = os.listdir(folder) # items = folders + files
        for i in items: i=folder+i; (walk if os.path.isdir(i) else allFiles).append(i)
    return allFiles

def listFiles2(root): # listdir/join (takes ~1.4x as long) (and uses '\\' instead)
    allFiles = []; walk = [root]
    while walk:
        folder = walk.pop(0); items = os.listdir(folder) # items = folders + files
        for i in items: i=os.path.join(folder,i); (walk if os.path.isdir(i) else allFiles).append(i)
    return allFiles

def listFiles3(root): # walk (takes ~1.5x as long)
    allFiles = []
    for folder, folders, files in os.walk(root):
        for file in files: allFiles+=[folder.replace("\\","/")+"/"+file] # folder+"\\"+file still ~1.5x
    return allFiles

def listFiles4(root): # walk/join (takes ~1.6x as long) (and uses '\\' instead)
    allFiles = []
    for folder, folders, files in os.walk(root):
        for file in files: allFiles+=[os.path.join(folder,file)]
    return allFiles


for i in range(100): files = listFiles1("src") # warm up

start = time.time()
for i in range(100): files = listFiles1("src") # listdir
print("Time taken: %.2fs"%(time.time()-start)) # 0.28s

start = time.time()
for i in range(100): files = listFiles2("src") # listdir and join
print("Time taken: %.2fs"%(time.time()-start)) # 0.38s

start = time.time()
for i in range(100): files = listFiles3("src") # walk
print("Time taken: %.2fs"%(time.time()-start)) # 0.42s

start = time.time()
for i in range(100): files = listFiles4("src") # walk and join
print("Time taken: %.2fs"%(time.time()-start)) # 0.47s

そのため、ご存じのとおり、listdirバージョンの方がはるかに効率的です。(そしてそれjoinは遅いです)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.