Каталог каталогов Python, подкаталог и файлы
Я пытаюсь сделать script, чтобы перечислить всю директорию, подкаталог и файлы в данном каталоге.
Я пробовал это:
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 struct будет:
/home/patate/directory/targetdirectory/123/456/789/file.txt
Он будет печатать:
/home/patate/directory/targetdirectory/file.txt
Мне нужен первый результат. Любая помощь будет принята с благодарностью! Спасибо.
Ответы
Ответ 1
Используйте 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
, вы также можете выполнять фактические вызовы ОС через них, например, чередовать в каталог, удалять путь, открывать файл, на который он указывает, и многое другое.
Ответ 2
На всякий случай... Получение всех файлов в каталоге и подкаталогах, соответствующих некоторому шаблону (например, *.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)
Ответ 3
Вот одна строка:
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...
цикле val for sublist in...
выравнивает список до одномерного. Цикл j
собирает список каждого базового имени файла и присоединяет его к текущему пути. Наконец, цикл i
перебирает все каталоги и подкаталоги.
В этом примере используется жестко заданный путь ./
в os.walk(...)
, вы можете добавить любую строку пути, какую 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('/')]
Ответ 4
Вы должны использовать "r" в своем соединении вместо "root"
Ответ 5
Вы можете взглянуть на этот образец, который я сделал. Он использует функцию 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)
Ответ 6
Не могли бы прокомментировать, так что пишите ответ здесь. Это самая ясная строка, которую я видел:
import os
[os.path.join(path, name) for path, subdirs, files in os.walk(root) for name in files]
Ответ 7
Немного проще в одну строку:
import os
from itertools import product, chain
chain.from_iterable([["\\".join(w) for w in product([i[0]], i[2])] for i in os.walk(dir)])
Ответ 8
Так как каждый пример здесь использует только 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
идет медленно)