Каталог списку 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а не rootїї використання, оскільки використання rootбуло б невірним.


У Python 3.4 був доданий модуль pathlib для полегшення маніпуляцій із контуром. Таким еквівалентом os.path.joinбуло б:

pathlib.PurePath(path, name)

Перевага pathlibполягає в тому, що ви можете використовувати різноманітні корисні методи на шляхах. Якщо ви використовуєте конкретний Pathваріант, ви також можете робити фактичні виклики ОС через них, як, наприклад, перетворення в каталог, видалення шляху, відкриття файлу, на який він вказує, та багато іншого.


це одна і єдина корисна відповідь на безліч запитань, які задаються "як отримати всі файли рекурсивно в python".
harrisonfooord

список розуміння: all_files = [os.path.join (шлях, ім'я) для імені у файлах для шляху, підкаталів, файлів у os.walk (папка)]
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 ...петля розгладжує список, щоб бути одновимірним. 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' НЕ в шлях.
Роман Рдгз

Так. Має бути, якщо '.git' не в i [0] .split ('/')]
Роман Rdgz

Я б порекомендував os.walkнад ручним циклом дірлінгу, генератори чудові, ідіть, використовуйте їх.
ThorSummoner

9

Не вдалося коментувати так письмову відповідь тут. Це найяскравіший рядок, який я бачив:

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

4

Ви можете подивитися на цей зразок, який я зробив. Він використовує функцію os.path.walk, яка застаріла, будь beware. Використовує список для зберігання всіх файлових шляхів

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це повільно)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.