Como posso listar todos os arquivos de um diretório no Python e adicioná-los a um list
?
Como posso listar todos os arquivos de um diretório no Python e adicioná-los a um list
?
Respostas:
os.listdir()
você terá tudo o que está em um diretório - arquivos e diretórios .
Se você quiser apenas arquivos, poderá filtrar isso usando os.path
:
from os import listdir
from os.path import isfile, join
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
ou você pode usar o os.walk()
que produzirá duas listas para cada diretório visitado - dividindo-se em arquivos e diretórios para você. Se você deseja apenas o diretório superior, basta interromper a primeira vez que ele produzir
from os import walk
f = []
for (dirpath, dirnames, filenames) in walk(mypath):
f.extend(filenames)
break
(_, _, filenames) = walk(mypath).next()
(se você está confiante de que a caminhada irá retornar pelo menos um valor, que deveria.)
f.extend(filenames)
não é realmente equivalente a f = f + filenames
. extend
será modificado f
no local, enquanto a adição cria uma nova lista em um novo local de memória. Isso significa que extend
geralmente é mais eficiente que +
, mas às vezes pode causar confusão se vários objetos mantiverem referências à lista. Por fim, vale a pena notar que isso f += filenames
é equivalente a f.extend(filenames)
, não f = f + filenames
.
_, _, filenames = next(walk(mypath), (None, None, []))
(_, _, filenames) = next(os.walk(mypath))
Eu prefiro usar o glob
módulo, pois combina correspondência e expansão de padrões.
import glob
print(glob.glob("/home/adam/*.txt"))
Ele retornará uma lista com os arquivos consultados:
['/home/adam/file1.txt', '/home/adam/file2.txt', .... ]
/home/user/foo/bar/hello.txt
, se estiver sendo executado no diretório foo
, o valor glob("bar/*.txt")
retornará bar/hello.txt
. Há casos em que você realmente deseja o caminho completo (ou seja, absoluto); para esses casos, consulte stackoverflow.com/questions/51520/…
glob.glob("*")
seria.
x=glob.glob("../train/*.png")
me dará uma matriz dos meus caminhos, desde que eu saiba o nome da pasta. Tão legal!
Obtenha uma lista de arquivos com Python 2 e 3
os.listdir()
Como obter todos os arquivos (e diretórios) no diretório atual (Python 3)
A seguir, são métodos simples para recuperar apenas arquivos no diretório atual, usando os
e a listdir()
função, no Python 3. Explorações adicionais demonstrarão como retornar pastas no diretório, mas você não terá o arquivo no subdiretório, para o qual você pode usar o walk - discutido mais tarde).
import os
arr = os.listdir()
print(arr)
>>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']
glob
Achei a glob mais fácil de selecionar o arquivo do mesmo tipo ou com algo em comum. Veja o seguinte exemplo:
import glob
txtfiles = []
for file in glob.glob("*.txt"):
txtfiles.append(file)
glob
com compreensão de lista
import glob
mylist = [f for f in glob.glob("*.txt")]
glob
com uma função
A função retorna uma lista da extensão fornecida (.txt, .docx ecc.) No argumento
import glob
def filebrowser(ext=""):
"Returns files with an extension"
return [f for f in glob.glob(f"*{ext}")]
x = filebrowser(".txt")
print(x)
>>> ['example.txt', 'fb.txt', 'intro.txt', 'help.txt']
glob
estendendo o código anterior
A função agora retorna uma lista de arquivos que correspondem à string que você passa como argumento
import glob
def filesearch(word=""):
"""Returns a list with all files with the word/extension in it"""
file = []
for f in glob.glob("*"):
if word[0] == ".":
if f.endswith(word):
file.append(f)
return file
elif word in f:
file.append(f)
return file
return file
lookfor = "example", ".py"
for w in lookfor:
print(f"{w:10} found => {filesearch(w)}")
resultado
example found => []
.py found => ['search.py']
Obter o nome completo do caminho com
os.path.abspath
Como você notou, você não tem o caminho completo do arquivo no código acima. Se você precisar ter o caminho absoluto, poderá usar outra função do os.path
módulo chamada _getfullpathname
, colocando o arquivo que obtém os.listdir()
como argumento. Existem outras maneiras de ter o caminho completo, como verificaremos mais tarde (substituí, como sugerido por mexmex, _getfullpathname with abspath
).
import os
files_path = [os.path.abspath(x) for x in os.listdir()]
print(files_path)
>>> ['F:\\documenti\applications.txt', 'F:\\documenti\collections.txt']
Obtenha o nome completo do caminho de um tipo de arquivo em todos os subdiretórios com
walk
Acho isso muito útil para encontrar coisas em muitos diretórios e me ajudou a encontrar um arquivo sobre o qual não me lembrava do nome:
import os
# Getting the current work directory (cwd)
thisdir = os.getcwd()
# r=root, d=directories, f = files
for r, d, f in os.walk(thisdir):
for file in f:
if file.endswith(".docx"):
print(os.path.join(r, file))
os.listdir()
: obtém arquivos no diretório atual (Python 2)
No Python 2, se você quiser a lista dos arquivos no diretório atual, precisará fornecer o argumento como '.' ou os.getcwd () no método os.listdir.
import os
arr = os.listdir('.')
print(arr)
>>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']
Para subir na árvore de diretórios
# Method 1
x = os.listdir('..')
# Method 2
x= os.listdir('/')
Obter arquivos:
os.listdir()
em um diretório específico (Python 2 e 3)
import os
arr = os.listdir('F:\\python')
print(arr)
>>> ['$RECYCLE.BIN', 'work.txt', '3ebooks.txt', 'documents']
Obter arquivos de um subdiretório específico com
os.listdir()
import os
x = os.listdir("./content")
os.walk('.')
- diretório atual
import os
arr = next(os.walk('.'))[2]
print(arr)
>>> ['5bs_Turismo1.pdf', '5bs_Turismo1.pptx', 'esperienza.txt']
next(os.walk('.'))
eos.path.join('dir', 'file')
import os
arr = []
for d,r,f in next(os.walk("F:\\_python")):
for file in f:
arr.append(os.path.join(r,file))
for f in arr:
print(files)
>>> F:\\_python\\dict_class.py
>>> F:\\_python\\programmi.txt
next(os.walk('F:\\')
- obtenha o caminho completo - compreensão da lista
[os.path.join(r,file) for r,d,f in next(os.walk("F:\\_python")) for file in f]
>>> ['F:\\_python\\dict_class.py', 'F:\\_python\\programmi.txt']
os.walk
- obtém o caminho completo - todos os arquivos em subdiretórios **
x = [os.path.join(r,file) for r,d,f in os.walk("F:\\_python") for file in f]
print(x)
>>> ['F:\\_python\\dict.py', 'F:\\_python\\progr.txt', 'F:\\_python\\readl.py']
os.listdir()
- obtenha apenas arquivos txt
arr_txt = [x for x in os.listdir() if x.endswith(".txt")]
print(arr_txt)
>>> ['work.txt', '3ebooks.txt']
Usando
glob
para obter o caminho completo dos arquivos
Se eu precisar do caminho absoluto dos arquivos:
from path import path
from glob import glob
x = [path(f).abspath() for f in glob("F:\\*.txt")]
for f in x:
print(f)
>>> F:\acquistionline.txt
>>> F:\acquisti_2018.txt
>>> F:\bootstrap_jquery_ecc.txt
Usando
os.path.isfile
para evitar diretórios na lista
import os.path
listOfFiles = [f for f in os.listdir() if os.path.isfile(f)]
print(listOfFiles)
>>> ['a simple game.py', 'data.txt', 'decorator.py']
Usando
pathlib
do Python 3.4
import pathlib
flist = []
for p in pathlib.Path('.').iterdir():
if p.is_file():
print(p)
flist.append(p)
>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speak_gui2.py
>>> thumb.PNG
Com list comprehension
:
flist = [p for p in pathlib.Path('.').iterdir() if p.is_file()]
Como alternativa, use em pathlib.Path()
vez depathlib.Path(".")
Use o método glob em pathlib.Path ()
import pathlib
py = pathlib.Path().glob("*.py")
for file in py:
print(file)
>>> stack_overflow_list.py
>>> stack_overflow_list_tkinter.py
Obtenha todos e apenas arquivos com os.walk
import os
x = [i[2] for i in os.walk('.')]
y=[]
for t in x:
for f in t:
y.append(f)
print(y)
>>> ['append_to_list.py', 'data.txt', 'data1.txt', 'data2.txt', 'data_180617', 'os_walk.py', 'READ2.py', 'read_data.py', 'somma_defaltdic.py', 'substitute_words.py', 'sum_data.py', 'data.txt', 'data1.txt', 'data_180617']
Obtenha apenas arquivos com o próximo e entre em um diretório
import os
x = next(os.walk('F://python'))[2]
print(x)
>>> ['calculator.bat','calculator.py']
Obtenha apenas diretórios com o próximo e entre em um diretório
import os
next(os.walk('F://python'))[1] # for the current dir use ('.')
>>> ['python3','others']
Obtenha todos os nomes dos subdiretórios com
walk
for r,d,f in os.walk("F:\\_python"):
for dirs in d:
print(dirs)
>>> .vscode
>>> pyexcel
>>> pyschool.py
>>> subtitles
>>> _metaprogramming
>>> .ipynb_checkpoints
os.scandir()
do Python 3.5 e superior
import os
x = [f.name for f in os.scandir() if f.is_file()]
print(x)
>>> ['calculator.bat','calculator.py']
# Another example with scandir (a little variation from docs.python.org)
# This one is more efficient than os.listdir.
# In this case, it shows the files only in the current directory
# where the script is executed.
import os
with os.scandir() as i:
for entry in i:
if entry.is_file():
print(entry.name)
>>> ebookmaker.py
>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speakgui4.py
>>> speak_gui2.py
>>> speak_gui3.py
>>> thumb.PNG
Exemplos:
Ex. 1: Quantos arquivos existem nos subdiretórios?
Neste exemplo, procuramos o número de arquivos incluídos em todo o diretório e seus subdiretórios.
import os
def count(dir, counter=0):
"returns number of files in dir and subdirs"
for pack in os.walk(dir):
for f in pack[2]:
counter += 1
return dir + " : " + str(counter) + "files"
print(count("F:\\python"))
>>> 'F:\\\python' : 12057 files'
Ex.2: Como copiar todos os arquivos de um diretório para outro?
Um script para fazer o pedido em seu computador, localizando todos os arquivos de um tipo (padrão: pptx) e copiando-os em uma nova pasta.
import os
import shutil
from path import path
destination = "F:\\file_copied"
# os.makedirs(destination)
def copyfile(dir, filetype='pptx', counter=0):
"Searches for pptx (or other - pptx is the default) files and copies them"
for pack in os.walk(dir):
for f in pack[2]:
if f.endswith(filetype):
fullpath = pack[0] + "\\" + f
print(fullpath)
shutil.copy(fullpath, destination)
counter += 1
if counter > 0:
print('-' * 30)
print("\t==> Found in: `" + dir + "` : " + str(counter) + " files\n")
for dir in os.listdir():
"searches for folders that starts with `_`"
if dir[0] == '_':
# copyfile(dir, filetype='pdf')
copyfile(dir, filetype='txt')
>>> _compiti18\Compito Contabilità 1\conti.txt
>>> _compiti18\Compito Contabilità 1\modula4.txt
>>> _compiti18\Compito Contabilità 1\moduloa4.txt
>>> ------------------------
>>> ==> Found in: `_compiti18` : 3 files
Ex. 3: Como obter todos os arquivos em um arquivo txt
Caso você queira criar um arquivo txt com todos os nomes de arquivos:
import os
mylist = ""
with open("filelist.txt", "w", encoding="utf-8") as file:
for eachfile in os.listdir():
mylist += eachfile + "\n"
file.write(mylist)
Exemplo: txt com todos os arquivos de um disco rígido
"""
We are going to save a txt file with all the files in your directory.
We will use the function walk()
"""
import os
# see all the methods of os
# print(*dir(os), sep=", ")
listafile = []
percorso = []
with open("lista_file.txt", "w", encoding='utf-8') as testo:
for root, dirs, files in os.walk("D:\\"):
for file in files:
listafile.append(file)
percorso.append(root + "\\" + file)
testo.write(file + "\n")
listafile.sort()
print("N. of files", len(listafile))
with open("lista_file_ordinata.txt", "w", encoding="utf-8") as testo_ordinato:
for file in listafile:
testo_ordinato.write(file + "\n")
with open("percorso.txt", "w", encoding="utf-8") as file_percorso:
for file in percorso:
file_percorso.write(file + "\n")
os.system("lista_file.txt")
os.system("lista_file_ordinata.txt")
os.system("percorso.txt")
Todo o arquivo de C: \ em um arquivo de texto
Esta é uma versão mais curta do código anterior. Mude a pasta onde começar a encontrar os arquivos, se precisar começar de outra posição. Esse código gera um arquivo de texto de 50 mb no meu computador com algo menos de 500.000 linhas com arquivos com o caminho completo.
import os
with open("file.txt", "w", encoding="utf-8") as filewrite:
for r, d, f in os.walk("C:\\"):
for file in f:
filewrite.write(f"{r + file}\n")
Como gravar um arquivo com todos os caminhos em uma pasta de um tipo
Com esta função, você pode criar um arquivo txt que terá o nome de um tipo de arquivo que você procura (por exemplo, pngfile.txt) com todo o caminho completo de todos os arquivos desse tipo. Às vezes, pode ser útil, eu acho.
import os
def searchfiles(extension='.ttf', folder='H:\\'):
"Create a txt file with all the file of a type"
with open(extension[1:] + "file.txt", "w", encoding="utf-8") as filewrite:
for r, d, f in os.walk(folder):
for file in f:
if file.endswith(extension):
filewrite.write(f"{r + file}\n")
# looking for png file (fonts) in the hard disk H:\
searchfiles('.png', 'H:\\')
>>> H:\4bs_18\Dolphins5.png
>>> H:\4bs_18\Dolphins6.png
>>> H:\4bs_18\Dolphins7.png
>>> H:\5_18\marketing html\assets\imageslogo2.png
>>> H:\7z001.png
>>> H:\7z002.png
(Novo) Encontre todos os arquivos e abra-os com tkinter GUI
Eu só queria adicionar neste 2019 um pequeno aplicativo para procurar todos os arquivos em um diretório e poder abri-los clicando duas vezes no nome do arquivo na lista.
import tkinter as tk
import os
def searchfiles(extension='.txt', folder='H:\\'):
"insert all files in the listbox"
for r, d, f in os.walk(folder):
for file in f:
if file.endswith(extension):
lb.insert(0, r + "\\" + file)
def open_file():
os.startfile(lb.get(lb.curselection()[0]))
root = tk.Tk()
root.geometry("400x400")
bt = tk.Button(root, text="Search", command=lambda:searchfiles('.png', 'H:\\'))
bt.pack()
lb = tk.Listbox(root)
lb.pack(fill="both", expand=1)
lb.bind("<Double-Button>", lambda x: open_file())
root.mainloop()
import os
os.listdir("somedirectory")
retornará uma lista de todos os arquivos e diretórios no "somedirectory".
glob.glob
os.listdir()
sempre retorna meros nomes de arquivos (não caminhos relativos). O glob.glob()
retorno é conduzido pelo formato do caminho do padrão de entrada.
Uma solução de uma linha para obter apenas a lista de arquivos (sem subdiretórios):
filenames = next(os.walk(path))[2]
ou caminhos absolutos:
paths = [os.path.join(path, fn) for fn in next(os.walk(path))[2]]
import os
. Parece menos conciso do que glob()
para mim.
glob()
o trataria como um arquivo. Seu método o trataria como um diretório.
Obtendo caminhos de arquivo completos de um diretório e de todos os seus subdiretórios
import os
def get_filepaths(directory):
"""
This function will generate the file names in a directory
tree by walking the tree either top-down or bottom-up. For each
directory in the tree rooted at directory top (including top itself),
it yields a 3-tuple (dirpath, dirnames, filenames).
"""
file_paths = [] # List which will store all of the full filepaths.
# Walk the tree.
for root, directories, files in os.walk(directory):
for filename in files:
# Join the two strings in order to form the full filepath.
filepath = os.path.join(root, filename)
file_paths.append(filepath) # Add it to the list.
return file_paths # Self-explanatory.
# Run the above function and store its results in a variable.
full_file_paths = get_filepaths("/Users/johnny/Desktop/TEST")
print full_file_paths
que imprimirá a lista:
['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']
Se desejar, você pode abrir e ler o conteúdo ou se concentrar apenas em arquivos com a extensão ".dat", como no código abaixo:
for f in full_file_paths:
if f.endswith(".dat"):
print f
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
Desde a versão 3.4, existem iteradores internos para isso, que são muito mais eficientes do que os.listdir()
:
pathlib
: Novo na versão 3.4.
>>> import pathlib
>>> [p for p in pathlib.Path('.').iterdir() if p.is_file()]
De acordo com o PEP 428 , o objetivo da pathlib
biblioteca é fornecer uma hierarquia simples de classes para manipular os caminhos do sistema de arquivos e as operações comuns que os usuários fazem sobre eles.
os.scandir()
: Novo na versão 3.5.
>>> import os
>>> [entry for entry in os.scandir('.') if entry.is_file()]
Observe que os.walk()
usa em os.scandir()
vez da os.listdir()
versão 3.5 e sua velocidade aumentou de 2 a 20 vezes, de acordo com o PEP 471 .
Deixe-me também recomendar a leitura do comentário de ShadowRanger abaixo.
list
. Poderia usar em p.name
vez do primeiro p
alternativamente, se preferir.
pathlib.Path()
instâncias, pois eles têm muitos métodos úteis que eu não gostaria de desperdiçar. Você também pode chamá str(p)
-los para nomes de caminhos.
os.scandir
solução será mais eficiente do que os.listdir
com uma os.path.is_file
verificação ou algo parecido, mesmo se você precisar de uma list
(para que você não se beneficie da iteração lenta), porque os.scandir
usa APIs fornecidas pelo SO que fornecem is_file
informações gratuitamente enquanto itera , não por arquivo de ida e volta para o disco para stat
eles em tudo (no Windows, os DirEntry
s te completa stat
informações de graça, em sistemas * NIX ele precisa stat
de informações para além is_file
, is_dir
etc., mas DirEntry
caches na primeira stat
por conveniência).
entry.name
para obter apenas o nome do arquivo ou entry.path
para obter o caminho completo. Não há mais os.path.join () em todo o lugar.
Quando a pergunta foi feita, imagino que o Python 2 fosse a versão LTS , no entanto, os exemplos de código serão executados pelo Python 3 ( .5 ) (eu os manterei o mais compatível possível com o Python 2 ; também, qualquer código pertencente a O Python que vou postar é da v3.5.4 - a menos que seja especificado de outra forma). Isso tem consequências relacionadas a outra palavra-chave na pergunta: " adicione-as a uma lista ":
>>> import sys >>> sys.version '2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]' >>> m = map(lambda x: x, [1, 2, 3]) # Just a dummy lambda function >>> m, type(m) ([1, 2, 3], <type 'list'>) >>> len(m) 3
>>> import sys >>> sys.version '3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)]' >>> m = map(lambda x: x, [1, 2, 3]) >>> m, type(m) (<map object at 0x000001B4257342B0>, <class 'map'>) >>> len(m) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'map' has no len() >>> lm0 = list(m) # Build a list from the generator >>> lm0, type(lm0) ([1, 2, 3], <class 'list'>) >>> >>> lm1 = list(m) # Build a list from the same generator >>> lm1, type(lm1) # Empty list now - generator already consumed ([], <class 'list'>)
Os exemplos serão baseados em um diretório chamado root_dir com a seguinte estrutura (este exemplo é para Win , mas também estou usando a mesma árvore no Lnx ):
E:\Work\Dev\StackOverflow\q003207219>tree /f "root_dir" Folder PATH listing for volume Work Volume serial number is 00000029 3655:6FED E:\WORK\DEV\STACKOVERFLOW\Q003207219\ROOT_DIR ¦ file0 ¦ file1 ¦ +---dir0 ¦ +---dir00 ¦ ¦ ¦ file000 ¦ ¦ ¦ ¦ ¦ +---dir000 ¦ ¦ file0000 ¦ ¦ ¦ +---dir01 ¦ ¦ file010 ¦ ¦ file011 ¦ ¦ ¦ +---dir02 ¦ +---dir020 ¦ +---dir0200 +---dir1 ¦ file10 ¦ file11 ¦ file12 ¦ +---dir2 ¦ ¦ file20 ¦ ¦ ¦ +---dir20 ¦ file200 ¦ +---dir3
[Python 3]: os. listdir ( caminho = '.' )
Retorne uma lista contendo os nomes das entradas no diretório fornecido pelo caminho. A lista está em ordem arbitrária e não inclui as entradas especiais
'.'
e'..'
...
>>> import os >>> root_dir = "root_dir" # Path relative to current dir (os.getcwd()) >>> >>> os.listdir(root_dir) # List all the items in root_dir ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [item for item in os.listdir(root_dir) if os.path.isfile(os.path.join(root_dir, item))] # Filter items and only keep files (strip out directories) ['file0', 'file1']
Um exemplo mais elaborado ( code_os_listdir.py ):
import os
from pprint import pformat
def _get_dir_content(path, include_folders, recursive):
entries = os.listdir(path)
for entry in entries:
entry_with_path = os.path.join(path, entry)
if os.path.isdir(entry_with_path):
if include_folders:
yield entry_with_path
if recursive:
for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive):
yield sub_entry
else:
yield entry_with_path
def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True):
path_len = len(path) + len(os.path.sep)
for item in _get_dir_content(path, include_folders, recursive):
yield item if prepend_folder_name else item[path_len:]
def _get_dir_content_old(path, include_folders, recursive):
entries = os.listdir(path)
ret = list()
for entry in entries:
entry_with_path = os.path.join(path, entry)
if os.path.isdir(entry_with_path):
if include_folders:
ret.append(entry_with_path)
if recursive:
ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive))
else:
ret.append(entry_with_path)
return ret
def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True):
path_len = len(path) + len(os.path.sep)
return [item if prepend_folder_name else item[path_len:] for item in _get_dir_content_old(path, include_folders, recursive)]
def main():
root_dir = "root_dir"
ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True)
lret0 = list(ret0)
print(ret0, len(lret0), pformat(lret0))
ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False)
print(len(ret1), pformat(ret1))
if __name__ == "__main__":
main()
Notas :
Saída :
(py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" "code_os_listdir.py" <generator object get_dir_content at 0x000001BDDBB3DF10> 22 ['root_dir\\dir0', 'root_dir\\dir0\\dir00', 'root_dir\\dir0\\dir00\\dir000', 'root_dir\\dir0\\dir00\\dir000\\file0000', 'root_dir\\dir0\\dir00\\file000', 'root_dir\\dir0\\dir01', 'root_dir\\dir0\\dir01\\file010', 'root_dir\\dir0\\dir01\\file011', 'root_dir\\dir0\\dir02', 'root_dir\\dir0\\dir02\\dir020', 'root_dir\\dir0\\dir02\\dir020\\dir0200', 'root_dir\\dir1', 'root_dir\\dir1\\file10', 'root_dir\\dir1\\file11', 'root_dir\\dir1\\file12', 'root_dir\\dir2', 'root_dir\\dir2\\dir20', 'root_dir\\dir2\\dir20\\file200', 'root_dir\\dir2\\file20', 'root_dir\\dir3', 'root_dir\\file0', 'root_dir\\file1'] 11 ['dir0\\dir00\\dir000\\file0000', 'dir0\\dir00\\file000', 'dir0\\dir01\\file010', 'dir0\\dir01\\file011', 'dir1\\file10', 'dir1\\file11', 'dir1\\file12', 'dir2\\dir20\\file200', 'dir2\\file20', 'file0', 'file1']
[Python 3]: os. scandir ( caminho = '.' ) ( Python 3.5 +, backport: [PyPI]: scandir )
Retorne um iterador de objetos os.DirEntry correspondentes às entradas no diretório fornecidas pelo caminho . As entradas são produzidas em ordem arbitrária e as entradas especiais
'.'
e'..'
não estão incluídas.Usar scandir () em vez de listdir () pode aumentar significativamente o desempenho do código que também precisa de informações sobre o tipo ou o atributo do arquivo, porque os objetos os.DirEntry expõem essas informações se o sistema operacional as fornecer ao varrer um diretório. Todos os métodos os.DirEntry podem executar uma chamada do sistema, mas is_dir () e is_file () geralmente requerem apenas uma chamada do sistema para links simbólicos; os.DirEntry.stat () sempre requer uma chamada do sistema no Unix, mas apenas uma para links simbólicos no Windows.
>>> import os >>> root_dir = os.path.join(".", "root_dir") # Explicitly prepending current directory >>> root_dir '.\\root_dir' >>> >>> scandir_iterator = os.scandir(root_dir) >>> scandir_iterator <nt.ScandirIterator object at 0x00000268CF4BC140> >>> [item.path for item in scandir_iterator] ['.\\root_dir\\dir0', '.\\root_dir\\dir1', '.\\root_dir\\dir2', '.\\root_dir\\dir3', '.\\root_dir\\file0', '.\\root_dir\\file1'] >>> >>> [item.path for item in scandir_iterator] # Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension) [] >>> >>> scandir_iterator = os.scandir(root_dir) # Reinitialize the generator >>> for item in scandir_iterator : ... if os.path.isfile(item.path): ... print(item.name) ... file0 file1
Notas :
os.listdir
[Python 3]: os. walk ( top, topdown = True, onerror = None, followlinks = False )
Gere os nomes de arquivo em uma árvore de diretórios, percorrendo a árvore de cima para baixo ou de baixo para cima. Para cada diretório na árvore com raiz no diretório superior (incluindo top si), ele produz um 3-tupla (
dirpath
,dirnames
,filenames
).
>>> import os >>> root_dir = os.path.join(os.getcwd(), "root_dir") # Specify the full path >>> root_dir 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir' >>> >>> walk_generator = os.walk(root_dir) >>> root_dir_entry = next(walk_generator) # First entry corresponds to the root dir (passed as an argument) >>> root_dir_entry ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir', ['dir0', 'dir1', 'dir2', 'dir3'], ['file0', 'file1']) >>> >>> root_dir_entry[1] + root_dir_entry[2] # Display dirs and files (direct descendants) in a single list ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [os.path.join(root_dir_entry[0], item) for item in root_dir_entry[1] + root_dir_entry[2]] # Display all the entries in the previous list by their full path ['E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file0', 'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1'] >>> >>> for entry in walk_generator: # Display the rest of the elements (corresponding to every subdir) ... print(entry) ... ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0', ['dir00', 'dir01', 'dir02'], []) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00', ['dir000'], ['file000']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00\\dir000', [], ['file0000']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir01', [], ['file010', 'file011']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02', ['dir020'], []) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020', ['dir0200'], []) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200', [], []) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1', [], ['file10', 'file11', 'file12']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2', ['dir20'], ['file20']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2\\dir20', [], ['file200']) ('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3', [], [])
Notas :
os.scandir
( os.listdir
em versões mais antigas)[Python 3]: glob. glob ( nome do caminho, *, recursivo = Falso ) ( [Python 3]: glob. iglob ( nome do caminho, *, recursivo = Falso ) )
Retorne uma lista possivelmente vazia de nomes de caminhos que correspondem ao nome do caminho , que deve ser uma sequência contendo uma especificação de caminho. o nome do caminho pode ser absoluto (curtir
/usr/src/Python-1.5/Makefile
) ou relativo (curtir../../Tools/*/*.gif
) e pode conter curingas no estilo de shell. Links simbólicos quebrados estão incluídos nos resultados (como no shell).
...
Alterado na versão 3.5 : Suporte para globs recursivos usando “**
”.
>>> import glob, os >>> wildcard_pattern = "*" >>> root_dir = os.path.join("root_dir", wildcard_pattern) # Match every file/dir name >>> root_dir 'root_dir\\*' >>> >>> glob_list = glob.glob(root_dir) >>> glob_list ['root_dir\\dir0', 'root_dir\\dir1', 'root_dir\\dir2', 'root_dir\\dir3', 'root_dir\\file0', 'root_dir\\file1'] >>> >>> [item.replace("root_dir" + os.path.sep, "") for item in glob_list] # Strip the dir name and the path separator from begining ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> for entry in glob.iglob(root_dir + "*", recursive=True): ... print(entry) ... root_dir\ root_dir\dir0 root_dir\dir0\dir00 root_dir\dir0\dir00\dir000 root_dir\dir0\dir00\dir000\file0000 root_dir\dir0\dir00\file000 root_dir\dir0\dir01 root_dir\dir0\dir01\file010 root_dir\dir0\dir01\file011 root_dir\dir0\dir02 root_dir\dir0\dir02\dir020 root_dir\dir0\dir02\dir020\dir0200 root_dir\dir1 root_dir\dir1\file10 root_dir\dir1\file11 root_dir\dir1\file12 root_dir\dir2 root_dir\dir2\dir20 root_dir\dir2\dir20\file200 root_dir\dir2\file20 root_dir\dir3 root_dir\file0 root_dir\file1
Notas :
os.listdir
[Python 3]: classe pathlib. Caminho ( * pathegments ) ( Python 3.4 +, backport: [PyPI]: pathlib2 )
>>> import pathlib >>> root_dir = "root_dir" >>> root_dir_instance = pathlib.Path(root_dir) >>> root_dir_instance WindowsPath('root_dir') >>> root_dir_instance.name 'root_dir' >>> root_dir_instance.is_dir() True >>> >>> [item.name for item in root_dir_instance.glob("*")] # Wildcard searching for all direct descendants ['dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [os.path.join(item.parent.name, item.name) for item in root_dir_instance.glob("*") if not item.is_dir()] # Display paths (including parent) for files only ['root_dir\\file0', 'root_dir\\file1']
Notas :
[Python 2]: dircache.listdir (caminho) ( somente Python 2 )
os.listdir
com o cachedef listdir(path):
"""List directory contents, using cache."""
try:
cached_mtime, list = cache[path]
del cache[path]
except KeyError:
cached_mtime, list = -1, []
mtime = os.stat(path).st_mtime
if mtime != cached_mtime:
list = os.listdir(path)
list.sort()
cache[path] = mtime, list
return list
[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) via [Python 3]: ctypes - Uma biblioteca de funções estrangeira para Python ( específico para POSIX )
ctypes é uma biblioteca de funções estrangeira para Python. Ele fornece tipos de dados compatíveis com C e permite funções de chamada em DLLs ou bibliotecas compartilhadas. Ele pode ser usado para agrupar essas bibliotecas em Python puro.
code_ctypes.py :
#!/usr/bin/env python3
import sys
from ctypes import Structure, \
c_ulonglong, c_longlong, c_ushort, c_ubyte, c_char, c_int, \
CDLL, POINTER, \
create_string_buffer, get_errno, set_errno, cast
DT_DIR = 4
DT_REG = 8
char256 = c_char * 256
class LinuxDirent64(Structure):
_fields_ = [
("d_ino", c_ulonglong),
("d_off", c_longlong),
("d_reclen", c_ushort),
("d_type", c_ubyte),
("d_name", char256),
]
LinuxDirent64Ptr = POINTER(LinuxDirent64)
libc_dll = this_process = CDLL(None, use_errno=True)
# ALWAYS set argtypes and restype for functions, otherwise it's UB!!!
opendir = libc_dll.opendir
readdir = libc_dll.readdir
closedir = libc_dll.closedir
def get_dir_content(path):
ret = [path, list(), list()]
dir_stream = opendir(create_string_buffer(path.encode()))
if (dir_stream == 0):
print("opendir returned NULL (errno: {:d})".format(get_errno()))
return ret
set_errno(0)
dirent_addr = readdir(dir_stream)
while dirent_addr:
dirent_ptr = cast(dirent_addr, LinuxDirent64Ptr)
dirent = dirent_ptr.contents
name = dirent.d_name.decode()
if dirent.d_type & DT_DIR:
if name not in (".", ".."):
ret[1].append(name)
elif dirent.d_type & DT_REG:
ret[2].append(name)
dirent_addr = readdir(dir_stream)
if get_errno():
print("readdir returned NULL (errno: {:d})".format(get_errno()))
closedir(dir_stream)
return ret
def main():
print("{:s} on {:s}\n".format(sys.version, sys.platform))
root_dir = "root_dir"
entries = get_dir_content(root_dir)
print(entries)
if __name__ == "__main__":
main()
Notas :
os.walk
formato do. Eu não me incomodei em torná-lo recursivo, mas a partir do código existente, isso seria uma tarefa bastante trivialSaída :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q003207219]> ./code_ctypes.py 3.5.2 (default, Nov 12 2018, 13:43:14) [GCC 5.4.0 20160609] on linux ['root_dir', ['dir2', 'dir1', 'dir3', 'dir0'], ['file1', 'file0']]
[ActiveState.Docs]: win32file.FindFilesW ( específico para Win )
Recupera uma lista de nomes de arquivos correspondentes, usando a API Unicode do Windows. Uma interface para as funções de fechamento da API FindFirstFileW / FindNextFileW / Find.
>>> import os, win32file, win32con >>> root_dir = "root_dir" >>> wildcard = "*" >>> root_dir_wildcard = os.path.join(root_dir, wildcard) >>> entry_list = win32file.FindFilesW(root_dir_wildcard) >>> len(entry_list) # Don't display the whole content as it's too long 8 >>> [entry[-2] for entry in entry_list] # Only display the entry names ['.', '..', 'dir0', 'dir1', 'dir2', 'dir3', 'file0', 'file1'] >>> >>> [entry[-2] for entry in entry_list if entry[0] & win32con.FILE_ATTRIBUTE_DIRECTORY and entry[-2] not in (".", "..")] # Filter entries and only display dir names (except self and parent) ['dir0', 'dir1', 'dir2', 'dir3'] >>> >>> [os.path.join(root_dir, entry[-2]) for entry in entry_list if entry[0] & (win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_ATTRIBUTE_ARCHIVE)] # Only display file "full" names ['root_dir\\file0', 'root_dir\\file1']
Notas :
win32file.FindFilesW
faz parte do [GitHub]: mhammond / pywin32 - Extensões do Python para Windows (pywin32) , que é um wrapper Python sobre o WINAPI sNotas :
O código deve ser portátil (exceto locais direcionados a uma área específica - que estão marcadas) ou cruzado:
Vários estilos de caminho (absoluto, parentes) foram usados nas variantes acima, para ilustrar o fato de que as "ferramentas" usadas são flexíveis nessa direção
os.listdir
e os.scandir
use opendir / readdir / closedir ( [MS.Docs]: função FindFirstFileW / [MS.Docs]: função FindNextFileW / [MS.Docs]: função FindClose ) (via [GitHub]: python / cpython - (master) cpython / Módulos / posixmodule.c )
win32file.FindFilesW
também usa essas funções ( específicas do Win ) (via [GitHub]: mhammond / pywin32 - (mestre) pywin32 / win32 / src / win32file.i )
_get_dir_content (do ponto 1 ) pode ser implementado usando qualquer uma dessas abordagens (algumas exigirão mais trabalho e outras menos)
filter_func=lambda x: True
(isso não desaparece qualquer coisa) e dentro de _get_dir_content algo como: if not filter_func(entry_with_path): continue
(se a função falhar em uma entrada, ela será ignorada), mas quanto mais complexo o código se tornar, mais tempo será necessário para executarNota bene! Como a recursão é usada, devo mencionar que fiz alguns testes no meu laptop ( Win 10 x64 ), totalmente não relacionados a esse problema, e quando o nível de recursão estava atingindo valores em algum lugar na faixa ( 990 .. 1000) ( recursionlimit - 1000 (padrão)), recebi o StackOverflow :). Se a árvore de diretórios exceder esse limite (não sou especialista em FS , não sei se isso é possível), isso pode ser um problema.
Devo também mencionar que não tentei aumentar o limite de recursão porque não tenho experiência na área (quanto posso aumentá-lo antes de aumentar também a pilha no SOnível), mas em teoria sempre haverá a possibilidade de falha, se a profundidade do diretório for maior que o limite de recursão mais alto possível (nessa máquina)
As amostras de código são apenas para fins demonstrativos. Isso significa que eu não levei em consideração o tratamento de erros (acho que não há nenhum bloco try / except / else / finalmente ), portanto o código não é robusto (o motivo é: mantê-lo o mais simples e curto possível ) Para a produção , o tratamento de erros também deve ser adicionado
Use Python apenas como um wrapper
O sabor mais famoso que conheço é o que chamo de abordagem de administrador do sistema :
grep
/ findstr
) ou a formatação de saída pode ser feita nos dois lados, mas não vou insistir nisso. Além disso, eu usei deliberadamente em os.system
vez de subprocess.Popen
.(py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os;os.system(\"dir /b root_dir\")" dir0 dir1 dir2 dir3 file0 file1
Em geral, essa abordagem deve ser evitada, pois se algum formato de saída de comando diferir ligeiramente entre versões / tipos de SO , o código de análise também deverá ser adaptado; para não mencionar diferenças entre localidades).
Gostei muito da resposta de adamk , sugerindo que você use glob()
, do módulo com o mesmo nome. Isso permite que você tenha correspondência de padrões com *
s.
Mas, como outras pessoas apontaram nos comentários, glob()
podem ser enganados por direções inconsistentes de barras. Para ajudar nisso, sugiro que você use as funções join()
e expanduser()
no os.path
módulo, e talvez a getcwd()
função no os
módulo também.
Como exemplos:
from glob import glob
# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')
O que foi dito acima é terrível - o caminho foi codificado e só funcionará no Windows entre o nome da unidade e os \
códigos codificados no caminho.
from glob import glob
from os.path import join
# Return everything under Users, admin, that contains a folder called wlp.
glob(join('Users', 'admin', '*', 'wlp'))
O exemplo acima funciona melhor, mas depende do nome da pasta, Users
que geralmente é encontrada no Windows e não é encontrada em outros sistemas operacionais. Também depende do usuário ter um nome específico admin
,.
from glob import glob
from os.path import expanduser, join
# Return everything under the user directory that contains a folder called wlp.
glob(join(expanduser('~'), '*', 'wlp'))
Isso funciona perfeitamente em todas as plataformas.
Outro ótimo exemplo que funciona perfeitamente entre plataformas e faz algo um pouco diferente:
from glob import glob
from os import getcwd
from os.path import join
# Return everything under the current directory that contains a folder called wlp.
glob(join(getcwd(), '*', 'wlp'))
Espero que esses exemplos o ajudem a ver o poder de algumas das funções que você pode encontrar nos módulos padrão da biblioteca Python.
**
funciona enquanto você definir recursive = True
. Veja os documentos aqui: docs.python.org/3.5/library/glob.html#glob.glob
Se você está procurando uma implementação Python de find , esta é uma receita que eu uso com bastante frequência:
from findtools.find_files import (find_files, Match)
# Recursively find all *.sh files in **/usr/bin**
sh_files_pattern = Match(filetype='f', name='*.sh')
found_files = find_files(path='/usr/bin', match=sh_files_pattern)
for found_file in found_files:
print found_file
Então criei um pacote PyPI e também há um repositório GitHub . Espero que alguém ache isso potencialmente útil para esse código.
Para obter melhores resultados, você pode usar o listdir()
métodoos
módulo junto com um gerador (um gerador é um iterador poderoso que mantém seu estado, lembra?). O código a seguir funciona bem com as duas versões: Python 2 e Python 3.
Aqui está um código:
import os
def files(path):
for file in os.listdir(path):
if os.path.isfile(os.path.join(path, file)):
yield file
for file in files("."):
print (file)
O listdir()
método retorna a lista de entradas para o diretório especificado. O método os.path.isfile()
retornará True
se a entrada fornecida for um arquivo. E o yield
operador sai da função, mas mantém seu estado atual e retorna apenas o nome da entrada detectada como um arquivo. Todos os itens acima nos permitem fazer um loop sobre a função do gerador.
O retorno de uma lista de caminhos de arquivo absolutos não recursa em subdiretórios
L = [os.path.join(os.getcwd(),f) for f in os.listdir('.') if os.path.isfile(os.path.join(os.getcwd(),f))]
os.path.abspath(f)
seria um substituto um pouco mais barato os.path.join(os.getcwd(),f)
.
cwd = os.path.abspath('.')
e depois usasse em cwd
vez de '.'
e os.getcwd()
para evitar cargas de chamadas de sistema redundantes.
import os
import os.path
def get_files(target_dir):
item_list = os.listdir(target_dir)
file_list = list()
for item in item_list:
item_dir = os.path.join(target_dir,item)
if os.path.isdir(item_dir):
file_list += get_files(item_dir)
else:
file_list.append(item_dir)
return file_list
Aqui eu uso uma estrutura recursiva.
Um professor sábio me disse uma vez que:
Quando existem várias maneiras estabelecidas de fazer algo, nenhuma delas é boa para todos os casos.
Assim, adicionarei uma solução para um subconjunto do problema: muitas vezes, queremos apenas verificar se um arquivo corresponde a uma sequência inicial e uma final, sem entrar em subdiretórios. Assim, gostaríamos de uma função que retorne uma lista de nomes de arquivos, como:
filenames = dir_filter('foo/baz', radical='radical', extension='.txt')
Se você deseja primeiro declarar duas funções, isso pode ser feito:
def file_filter(filename, radical='', extension=''):
"Check if a filename matches a radical and extension"
if not filename:
return False
filename = filename.strip()
return(filename.startswith(radical) and filename.endswith(extension))
def dir_filter(dirname='', radical='', extension=''):
"Filter filenames in directory according to radical and extension"
if not dirname:
dirname = '.'
return [filename for filename in os.listdir(dirname)
if file_filter(filename, radical, extension)]
Essa solução pode ser facilmente generalizada com expressões regulares (e você pode adicionar um pattern
argumento, se não desejar que seus padrões sempre atinjam o início ou o final do nome do arquivo).
Outra variante muito legível para o Python 3.4+ está usando pathlib.Path.glob:
from pathlib import Path
folder = '/foo'
[f for f in Path(folder).glob('*') if f.is_file()]
É simples tornar mais específico, por exemplo, procure apenas arquivos de origem Python que não são links simbólicos, também em todos os subdiretórios:
[f for f in Path(folder).glob('**/*.py') if not f.is_symlink()]
Aqui está minha função de propósito geral para isso. Ele retorna uma lista de caminhos de arquivos, em vez de nomes de arquivos, desde que achei mais útil. Ele possui alguns argumentos opcionais que o tornam versátil. Por exemplo, costumo usá-lo com argumentos como pattern='*.txt'
ou subfolders=True
.
import os
import fnmatch
def list_paths(folder='.', pattern='*', case_sensitive=False, subfolders=False):
"""Return a list of the file paths matching the pattern in the specified
folder, optionally including files inside subfolders.
"""
match = fnmatch.fnmatchcase if case_sensitive else fnmatch.fnmatch
walked = os.walk(folder) if subfolders else [next(os.walk(folder))]
return [os.path.join(root, f)
for root, dirnames, filenames in walked
for f in filenames if match(f, pattern)]
Fornecerei uma amostra de um liner em que o caminho de origem e o tipo de arquivo possam ser fornecidos como entrada. O código retorna uma lista de nomes de arquivos com extensão csv. Use . caso todos os arquivos precisem ser retornados. Isso também verifica recursivamente os subdiretórios.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Modifique as extensões de arquivo e o caminho de origem, conforme necessário.
glob
, basta usar glob('**/*.csv', recursive=True)
. Não é necessário combinar isso com o os.walk()
recursivo ( recursive
e **
são suportados desde o Python 3.5).
Para python2: pip install rglob
import rglob
file_list=rglob.rglob("/home/base/dir/", "*")
print file_list
dircache é " Descontinuado desde a versão 2.6: O módulo dircache foi removido no Python 3.0."
import dircache
list = dircache.listdir(pathname)
i = 0
check = len(list[0])
temp = []
count = len(list)
while count != 0:
if len(list[i]) != check:
temp.append(list[i-1])
check = len(list[i])
else:
i = i + 1
count = count - 1
print temp