Каталог, подкаталог и файлы списка 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

Мне нужен первый результат. Любая помощь будет принята с благодарностью! Спасибо.

thomytheyon
источник

Ответы:

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 (папка)]
Нир
В Python3 используйте круглые скобки для функции печатиprint(os.path.join(path, name))
Ehsan
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('/')]
ThorSummoner
источник
Это работает, но чтобы исключить директорию .git, вам нужно проверить, НЕ входит ли .git в путь.
Роман Rdgz
Ага. Должно быть, если '.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, которая устарела, будьте осторожны. Использует список для хранения всех путей к файлам.

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)
devsaw
источник
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

Поскольку в каждом примере здесь просто используется walk(with join), я хотел бы показать хороший пример и сравнение с 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медленно)

лужа
источник